SQL-非规范化数据导出到平面文件混合分隔符

SQL-非规范化数据导出到平面文件混合分隔符,sql,db2,Sql,Db2,我有一个扁平的非规范化表格: PRODUCT_ID LOCATION PARTNUMBER PRICE STATUS 1234567890 9999 5555 10.99 A 1234567890 8888 5555 11.99 A 1234567890 7777 5555 9.99 B 98

我有一个扁平的非规范化表格:

PRODUCT_ID     LOCATION        PARTNUMBER      PRICE   STATUS
1234567890     9999            5555            10.99   A
1234567890     8888            5555            11.99   A
1234567890     7777            5555             9.99   B
9876543210     9999            3333            15.99   A
9876543210     4444            3333            14.99   A
...
我需要对此进行查询,以生成类似以下内容的输出文件:

1234567890|9999|5555|10.99|A,8888|5555|11.99|A,7777|5555|9.99|B
9876543210|9999|3333|15.99|A,4444|3333|14.99|A
...
select a.product_id || 
     coalesce((select '|' || b.location || '|' || b.partnumber  || '|' || 
                             b.price || '|' || trim(b.status)  || ','
               from session.products b 
               where b.location = '9999' and b.product_id = a.product_id), '') || 

     coalesce((select '|' || c.location || '|' || c.partnumber  || '|' || 
                                 c.price || '|' || trim(c.status)  || ','
               from session.products c 
               where c.location = '8888' and c.product_id = a.product_id), '') 
from (select distinct product_id as product_id from session.products) as a
因此基本上是一种数据格式:

产品标识|位置1 |零件号1 |价格1 |状态1,位置N |零件号|价格N,状态N


我不确定从何处开始……我应该使用嵌套查询吗?

您需要创建一个游标以在表中循环。 使用变量控制表中的每一行是指同一产品还是指新产品

大概是这样的:

DECLARE @OLD_PRODUCT_ID int
set @OLD_PRODUCT_ID = -1

DECLARE MyCursor CURSOR FOR 
select PRODUCT_ID, LOCATION, PARTNUMBER, PRICE, STATUS
FROM YourTable

OPEN MyCursor;

FETCH NEXT FROM MyCursor 
INTO @PRODUCT_ID, @LOCATION, @PARTNUMBER, @PRICE, @STATUS --declare these variables

WHILE @@FETCH_STATUS = 0 BEGIN
    if (@PRODUCT_ID = @OLD_PRODUCT_ID) begin
        -- use the same line
    end ele begin
        -- new product = new line
    end

    @OLD_PRODUCT_ID = @PRODUCT_ID
    FETCH NEXT FROM MyCursor 
    INTO @PRODUCT_ID, @LOCATION, @PARTNUMBER, @PRICE, @STATUS

END
CLOSE MyCursor;
DEALLOCATE MyCursor;

还有一些方法可以通过w/o循环来实现,但是sql更难实现

位置列表是否有边界且较小

如果是这样,您可以这样做:

1234567890|9999|5555|10.99|A,8888|5555|11.99|A,7777|5555|9.99|B
9876543210|9999|3333|15.99|A,4444|3333|14.99|A
...
select a.product_id || 
     coalesce((select '|' || b.location || '|' || b.partnumber  || '|' || 
                             b.price || '|' || trim(b.status)  || ','
               from session.products b 
               where b.location = '9999' and b.product_id = a.product_id), '') || 

     coalesce((select '|' || c.location || '|' || c.partnumber  || '|' || 
                                 c.price || '|' || trim(c.status)  || ','
               from session.products c 
               where c.location = '8888' and c.product_id = a.product_id), '') 
from (select distinct product_id as product_id from session.products) as a
您可以在其中扩展每个位置的语句


对于sql中的一组无界位置,有很多方法可以做到这一点,但读/写/调试并不容易,而且+Diego的游标解决方案可能更可取。

有趣的是,您可以递归地执行此操作:

WITH Ordered_Data (product_id, orderIndex, dataString) as (
     SELECT product_id, location, partnumber, price, status, 
         ROW_NUMBER() OVER(PARTITION_BY product_id ORDER BY product_id, location ASC),
            product_id || '|' || location || '|' || partnumber || '|' ||     
            price || '|' || status   
     FROM Product_Location),

     Combined_Data(product_id, orderIndex, dataString) as (
     SELECT a.product_id, a.orderIndex, a.dataString
     FROM Ordered_Data as a
     JOIN (SELECT product_id, MAX(orderIndex) as orderIndex
           FROM Ordered_Data 
           GROUP BY product_id) as b
     ON b.product_id = a.product_id
     AND b.orderIndex = a.orderIndex
     UNION ALL
     SELECT b.product_id, a.orderIndex, b.dataString || ',' || a.dataString
     FROM Ordered_Data as a
     JOIN Combined_Data as b
     ON b.product_id = a.product_id
     AND b.orderIndex - 1 = a.orderIndex)

SELECT dataString
FROM Combined_Data
WHERE orderIndex = 1
这将产生预期的:

9876543210|9999|3333|15.99|A,9876543210|4444|3333|14.99|A                            
1234567890|9999|5555|10.99|A,1234567890|8888|5555|11.99|A,1234567890|7777|5555|9.99|B 
我不能保证它的运行速度——特别是,你需要一个索引(
product\u id
location
)(或类似的,并调整语句)。我相信DB2足够聪明,可以向后读取标记,所以方向应该不太重要


顺便说一句,对于MySQL、SQL Server、Postgres、Oracle等等,我希望价格是十进制的,而不是浮点的,您想对规范化表进行非规范化吗?您知道您基本上放弃了使用大多数
load
类型函数的权利,对吗?我知道iSeries上的DB2在尝试加载到(单个列)表时(不确定在哪里使用)不会接受无限长/锯齿长的行。无论你把它给谁,都可能需要单独解析出来;我更希望这张桌子能“出口”。哦,无论如何,这些数据可能不会完全规范化……不要忘记select语句中的ORDER BY,否则这将不起作用!