SQL: Вывести несколько строк, соединенных слева, как одну запись для файла CSV - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть 3 таблицы:

Stock - ID, Description, Quantity etc
Equipment - ID, Description
LinkStockEquipment - StockID, EquipmentID, Quantity

Для каждой позиции на складе может потребоваться несколько типов оборудования.

Я хочу вывести все данные в файл CSV для клиента.

В идеале они хотят:
StockID, StockDescription, StockQuantity, Equipment1, Equipment1Qty, Equipment2, Equipment2Qty, Equipment3, Equipment3Qty etc

Итак, моя отправная точка:

SELECT * FROM Stock 
LEFT JOIN LinkStockEquipment ON LinkStockEquipment.StockID = Stock.ID 
LEFT JOIN Equipment ON Equipment.ID = LinkStockEquipment.EquipmentID

Но, конечно, это просто дает мне несколько строк, когда на один товар имеется несколько типов оборудования.Я мог бы просто взять верхнюю или нижнюю строки, используя SORT и MAX или MIN, но как мне тогда получить доступ к оставшимся строкам, одну за другой, чтобы связать их.

Может ли это быть что-то вроде (синтаксис неправильный, нопытаюсь донести сообщение)

SELECT * FROM Stock 
LEFT JOIN LinkStockEquipment AS LSE1 ON LSE1.StockID = Stock.ID LIMIT 1
LEFT JOIN LinkStockEquipment AS LSE2 ON LSE2.StockID = Stock.ID AND LSE1.StockID <> LSE2.StockID LIMIT 1
LEFT JOIN LinkStockEquipment AS LSE3 ON LSE3.StockID = Stock.ID AND LSE1.StockID <> LSE2.StockID AND LSE2.StockID <> LSE3.StockID LIMIT 1
LEFT JOIN Equipment ON Equipment.ID = LinkStockEquipment.EquipmentID

Извиняюсь, если на этот вопрос уже был дан прямой ответ, я раньше использовал только базовый SQL, поэтому я не до конца понял другие ответы на подобные вопросы.

MySQL Left Join многие в одну строку может делать то, что я хочу, но мне также нужно количество каждого типа экипировки, чтобы это не было решением.

Обновление 1: Я также рассмотрел Строка сводки MySQL для динамического числа столбцов Однако я не видел, как это можно применить, когда мне нужно и оборудование, и количество каждый раз, а нетолько один элемент для поворота.Я буду читать больше о Pivoting.

Обновление 2: Чтение о повороте даст мне отдельный столбец для каждого типа оборудования, но может быть 100 различных типов оборудования.Тем не менее, каждый товар может иметь только 2 или 3 из этих 100 различных типов.Я только поэтому хочу перечислить, что эти типы оборудования не являются столбцами для каждого.

Учитывая:

Stock ID | Equipment ID | Equipment Qty
---------------------------------------
A1       | E1           | 5
A1       | E2           | 3
A2       | E3           | 4
A2       | E4           | 6
A3       | E5           | 2

Я хотел бы

Stock ID | Eqpmnt ID 1 | Eqpmnt Qty 1 | Eqpmnt ID 2 | Eqpmnt Qty 2
------------------------------------------------------------------
A1       | E1          | 5            | E2          | 3
A2       | E3          | 4            | E4          | 6
A3       | E5          | 2            |             |

Не

Stock ID | E1 | E2 | E3 | E4 | E5 
------------------------------------------------------------------
A1       | 5  | 3  |    |    |
A2       |    |    | 4  | 6  |
A3       |    |    |    |    | 2

Разве я не неправильно понял поворот?

Обновление и результат: По какой-то причине я не могу установить это как ответ на вопрос, однако в случае, если это поможет кому-то еще...

Благодаря Хуану ниже я добавил дополнительную строку в свою таблицу LinkStockEquipment, используя информацию из этого вопроса: Значение приращения mysql на основе предыдущей записи

UPDATE t1
SET t1.Counter = t2.Counter
FROM  LinkStockEquipment t1
LEFT JOIN
(
    SELECT
    t.EquipmentID,
    t.StockID ,
    (SELECT COUNT(*) FROM [LinkStockEquipment] AS x WHERE x.EquipmentID <= t.EquipmentID
    AND x.StockID = t.StockID) AS Counter
    FROM [LinkStockEquipment] t
) as t2
    ON t1.EquipmentID= t2.EquipmentID AND t1.StockID = t2.StockID 

Итак, таблица выглядит следующим образом:

Stock ID | Equipment ID | Equipment Qty | Counter
-------------------------------------------------
A1       | E1           | 5             | 1
A1       | E2           | 3             | 2
A2       | E3           | 4             | 1
A2       | E4           | 6             | 2
A3       | E5           | 2             | 1

Теперь я могу поворачиваться, поэтому, используя

SELECT P.StockID, P.[1], L1.Qty, P.[2], L2.Qty, P.[3], L3.Qty
FROM (SELECT StockID, EquipmentID, Counter
FROM [LinkStockEquipment]) AS D
PIVOT(MAX(EquipmentID) FOR Counter IN([1],[2],[3])) AS P
LEFT JOIN [LinkStockEquipment] L1 ON L1.StockID = P.StockID
AND L1.EquipmentID = P.[1]
LEFT JOIN [LinkStockEquipment] L2 ON L2.StockID = P.StockID 
AND L2.EquipmentID = P.[2]
LEFT JOIN [LinkStockEquipment] L3 ON L3.StockID = P.StockID 
AND L3.EquipmentID = P.[3]

, я могу оставить соединение в деталях таблицы Stock и получить желаемый результат.

1 Ответ

0 голосов
/ 11 декабря 2018

Если у вас есть фиксированное количество оборудования на складе (я предполагаю, что 3 для этого)

Вы можете сделать сводку, используя GROUP BY.

SQL DEMO

WITH tmpResult as (
    SELECT 
         [Stock ID],
         'Equipment ID ' + CAST(rn AS VARCHAR(16)) as lblEq,
         [Equipment ID],
         [Equipment Qty]
    FROM ( SELECT *, row_number() over (partition by [Stock ID] ORDER BY [Equipment ID]) as rn
           FROM LinkStockEquipment ) as rows
)    
SELECT [Stock ID], 
       MAX( CASE WHEN lblEq = 'Equipment ID 1' THEN [Equipment ID]  END) as [Eqp ID 1],
       MAX( CASE WHEN lblEq = 'Equipment ID 1' THEN [Equipment Qty] END) as [Eqp Qty 1],
       MAX( CASE WHEN lblEq = 'Equipment ID 2' THEN [Equipment ID]  END) as [Eqp ID 2],
       MAX( CASE WHEN lblEq = 'Equipment ID 2' THEN [Equipment Qty] END) as [Eqp Qty 2],
       MAX( CASE WHEN lblEq = 'Equipment ID 3' THEN [Equipment ID]  END) as [Eqp ID 3],
       MAX( CASE WHEN lblEq = 'Equipment ID 3' THEN [Equipment Qty] END) as [Eqp Qty 3]
FROM       tmpResult
GROUP BY [Stock ID];

ВЫХОД

enter image description here

Теперь, если вы хотите использовать PIVOT,Важной частью является подготовка данных.В этом случае я должен преобразовать количество в строку.Опять же, вам нужно знать количество полей, которые вы хотите повернуть

SQL DEMO

WITH tmpResult as (
    SELECT 
         [Stock ID],
         'Eqp ID ' + CAST(rn AS VARCHAR(16)) as label,
         [Equipment ID] as [Value]
    FROM ( SELECT *, row_number() over (partition by [Stock ID] ORDER BY [Equipment ID]) as rn
           FROM LinkStockEquipment ) as rows

    UNION ALL

    SELECT 
         [Stock ID],
         'Eqp Qty ' + CAST(rn AS VARCHAR(16)) as label,
         CAST([Equipment Qty] AS VARCHAR(16))  as [Value]
    FROM ( SELECT *, row_number() over (partition by [Stock ID] ORDER BY [Equipment ID]) as rn
           FROM LinkStockEquipment ) as rows

)    
SELECT [Stock ID], 
       [Eqp ID 1], [Eqp Qty 1],
       [Eqp ID 2], [Eqp Qty 2]       
FROM   ( SELECT * FROM tmpResult ) as x
PIVOT ( 
        max( [Value] ) 
        for label in  ( [Eqp ID 1], [Eqp Qty 1], [Eqp ID 2], [Eqp Qty 2] )
      ) as pvt 

OUTPUT

enter image description here

Теперь, если вы не знаете, сколько у вас оборудования, вам нужен динамический PIVOT.

SQLDEMO

Сначала вам понадобится временная таблица.

SELECT 
     [Stock ID],
     [label],
     [Value]
INTO tmpResult
FROM (
    SELECT 
         [Stock ID],
         'Eqp ID ' + CAST(rn AS VARCHAR(16)) as label,
         [Equipment ID] as [Value]
    FROM ( SELECT *, row_number() over (partition by [Stock ID] ORDER BY [Equipment ID]) as rn
           FROM LinkStockEquipment ) as rows

    UNION ALL

    SELECT 
         [Stock ID],
         'Eqp Qty ' + CAST(rn AS VARCHAR(16)) as label,
         CAST([Equipment Qty] AS VARCHAR(16))  as [Value]
    FROM ( SELECT *, row_number() over (partition by [Stock ID] ORDER BY [Equipment ID]) as rn
           FROM LinkStockEquipment ) as rows
    ) as x;

Затем вам нужно подготовить сводный запрос:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.label)
            FROM tmpResult c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'');

SELECT @cols; 

set @query = 'SELECT [Stock ID], ' + @cols + ' FROM  
            (
                SELECT *
                FROM tmpResult
           ) x
            pivot 
            (
                 max(Value)
                for label in (' + @cols + ')
            ) p '

execute(@query);

OUTPUT

Здесь проблема заключается в порядке столбцов.Я постараюсь выяснить, можно ли это исправить.

enter image description here

...