SQL与连接和数据透视表

时间:2017-01-31 22:19:10

标签: sql sql-server tsql

今天我花了6个多小时试图找出这个SQL解决方案无济于事。老实说,我在一些搜索之后想出来,我必须使用PIVOT指令(之前从未见过)来获取我之后的内容,从那时起我就试图在使用join命令时找出这个命令。我不是那么聪明。

这就是我想要做的事情:

我有这些表格(我显示了我认为与此问题相关的表格,因为还有一些其他INNER JOINS参考其他表格):

enter image description here

enter image description here

enter image description here

这个查询:

SELECT [Easytool_data].[dbo].[estoque].[id] AS ID
      ,[Easytool_data].[dbo].[estoque].[barras] AS PartNumber
      ,[Easytool_data].[dbo].[estoque].[codigo] AS Codigo
      ,[Easytool_data].[dbo].[estoque].[descricao] AS Descricao
      ,[Easytool_data].[dbo].[estoque].[um] AS Unidade
      ,[Easytool_data].[dbo].[familias].[Descricao] AS Familia
      ,[Easytool_data].[dbo].[estoque].[fabricante] AS Fabricante
      ,[Easytool_data].[dbo].[estoque].[modelo] AS Modelo
      ,[Easytool_data].[dbo].[estoque].[armazenagem] AS Local
      ,[Easytool_data].[dbo].[status].[Descricao] AS Situacao
      ,[Easytool_data].[dbo].[estoque].[custo] AS Preco
      ,[Easytool_data].[dbo].[estoque].[sd_atual] AS Saldo
      ,[Easytool_data].[dbo].[local_estoque].[descricao] AS Estoque
      ,[Easytool_data].[dbo].[local_estocado].[quantidade] AS Quantidade

FROM [Easytool_data].[dbo].[estoque] 

INNER JOIN [Easytool_data].[dbo].[familias]       
ON [Easytool_data].[dbo].[estoque].[id_familia] = [Easytool_data].[dbo].[familias].[Id]
INNER JOIN [Easytool_data].[dbo].[status]
ON [Easytool_data].[dbo].[estoque].[id_status] = [Easytool_data].[dbo].[status].[Id]
INNER JOIN [Easytool_data].[dbo].[local_estocado]
ON [Easytool_data].[dbo].[estoque].[id] = [Easytool_data].[dbo].[local_estocado].[id_estoque]
INNER JOIN [Easytool_data].[dbo].[local_estoque]
ON [Easytool_data].[dbo].[local_estocado].[id_local_estoque] = [Easytool_data].[dbo].[local_estoque].[id]

WHERE  [Easytool_data].[dbo].[estoque].[id] = 3954

返回此内容:

ID     | PartNumber | Codigo    | Descricao   | Unidade | Familia   | Fabricante | Modelo | Local     | Situacao | Preco | Saldo | Estoque     | Quantidade
----------------------------------------------------------------------------------------------------------------------------------------------------
3954   | OSPÇ0024   |  OSPÇ0024 | PINÇA ER 25 | UNIDADE | PINÇA     | SANDVIK    | NULL   | PI 01-D-2 | ATIVO    | 25    | 2     | CENTRAL     | 1
----------------------------------------------------------------------------------------------------------------------------------------------------
3954   | OSPÇ0024   |  OSPÇ0024 | PINÇA ER 25 | UNIDADE | PINÇA     | SANDVIK    | NULL   | PI 01-D-2 | ATIVO    | 25    | 2     | ROTATIVO 0  | 0
----------------------------------------------------------------------------------------------------------------------------------------------------
3954   | OSPÇ0024   |  OSPÇ0024 | PINÇA ER 25 | UNIDADE | PINÇA     | SANDVIK    | NULL   | PI 01-D-2 | ATIVO    | 25    | 2     | REFORMA  0  | 0
----------------------------------------------------------------------------------------------------------------------------------------------------
3954   | OSPÇ0024   |  OSPÇ0024 | PINÇA ER 25 | UNIDADE | PINÇA     | SANDVIK    | NULL   | PI 01-D-2 | ATIVO    | 25    | 2     | EMPRÉSTIMO  | 1

我想让它归还:

ID     | PartNumber |   Codigo  | Descricao   | Unidade |   Familia | Fabricante | Modelo | Local     | Situacao | Preco | Saldo | Estoque | Quantidade | Estoque    | Quantidade | Estoque   | Quantidade | Estoque    | Quantidade
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3954   |OSPÇ0024   |  OSPÇ0024  | PINÇA ER 25 | UNIDADE | PINÇA     | SANDVIK    | NULL   | PI 01-D-2 | ATIVO    | 25    | 2     | CENTRAL | 1          | ROTATIVO 0 | 0          | REFORMA 0 | 0          | EMPRÉSTIMO | 1
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

我最近才知道PIVOT可以用来实现这个目标,但我完全不知道如何将它与几个INNER JOIN命令一起使用,就像我的查询中的命令一样。我曾用几种不同的方式尝试过它,但总是出错。

有人能举例说明我在使用类似于我的查询之后如何实现我的目标吗?

我在电路板上搜索过,与我的查询相比,我发现的所有示例都过于复杂或简单。我并不懒惰,我愿意尽我所能去学习,但现在似乎无法实现。

如果有人能在这里说清楚,我会非常感激,

谢谢 丹尼尔

3 个答案:

答案 0 :(得分:1)

如果你用上面的查询替换我称为initial_query_output的全表,Common Table Expression,那么这应该有效:

WITH initial_query_output (
  ID
, PartNumber
, Codigo
, Descricao
, Unidade
, Familia
, Fabricante
, Modelo
, Local
, Situacao
, Preco
, Saldo
, Estoque
, Quantidade
) AS (
-- replace with your initial query from here
          SELECT 3954,'OSPÇ002','OSPÇ00','PINÇA ER 2','UNIDAD','PINÇ','SANDVI','NUL','PI 01-D-','ATIV',25,2,'CENTRAL'    ,1
UNION ALL SELECT 3954,'OSPÇ002','OSPÇ00','PINÇA ER 2','UNIDAD','PINÇ','SANDVI','NUL','PI 01-D-','ATIV',25,2,'ROTATIVO 0' ,0
UNION ALL SELECT 3954,'OSPÇ002','OSPÇ00','PINÇA ER 2','UNIDAD','PINÇ','SANDVI','NUL','PI 01-D-','ATIV',25,2,'REFORMA  0' ,0
UNION ALL SELECT 3954,'OSPÇ002','OSPÇ00','PINÇA ER 2','UNIDAD','PINÇ','SANDVI','NUL','PI 01-D-','ATIV',25,2,'EMPRÉSTIMO' ,1
-- replace with your initial query until here
)
SELECT
  ID
, PartNumber
, Codigo
, Descricao
, Unidade
, Familia
, Fabricante
, Modelo
, Local
, Situacao
, Preco
, Saldo
, MAX(CASE Estoque WHEN 'CENTRAL'    THEN Estoque    END) AS Estoque1
, MAX(CASE Estoque WHEN 'CENTRAL'    THEN Quantidade END) AS Quantidade1
, MAX(CASE Estoque WHEN 'ROTATIVO 0' THEN Estoque    END) AS Estoque2
, MAX(CASE Estoque WHEN 'ROTATIVO 0' THEN Quantidade END) AS Quantidade2
, MAX(CASE Estoque WHEN 'REFORMA  0' THEN Estoque    END) AS Estoque3
, MAX(CASE Estoque WHEN 'REFORMA  0' THEN Quantidade END) AS Quantidade3
, MAX(CASE Estoque WHEN 'EMPRÉSTIMO' THEN Estoque    END) AS Estoque4
, MAX(CASE Estoque WHEN 'EMPRÉSTIMO' THEN Quantidade END) AS Quantidade4
FROM initial_query_output
GROUP BY
  ID
, PartNumber
, Codigo
, Descricao
, Unidade
, Familia
, Fabricante
, Modelo
, Local
, Situacao
, Preco
, Saldo

ID   |PartNumber|Codigo|Descricao |Unidade|Familia|Fabricante|Modelo|Local   |Situacao|Preco|Saldo|Estoque1|Quantidade1|Estoque2  |Quantidade2|Estoque3  |Quantidade3|Estoque4  |Quantidade4
3,954|OSPÇ002   |OSPÇ00|PINÇA ER 2|UNIDAD |PINÇ   |SANDVI    |NUL   |PI 01-D-|ATIV    |   25|    2|CENTRAL |          1|ROTATIVO 0|          0|REFORMA  0|          0|EMPRÉSTIMO|          1

答案 1 :(得分:1)

仅使用SQL进行水平旋转通常是使用描述性的,先前垂直的列;与用于CASE表达式的相同,作为列名。 像这样:

WITH initial_query_output (
  ID
, PartNumber
, Codigo
, Descricao
, Unidade
, Familia
, Fabricante
, Modelo
, Local
, Situacao
, Preco
, Saldo
, Estoque
, Quantidade
) AS (
          SELECT 3954,'OSPÇ002','OSPÇ00','PINÇA ER 2','UNIDAD','PINÇ','SANDVI','NUL','PI 01-D-','ATIV',25,2,'CENTRAL'    ,1
UNION ALL SELECT 3954,'OSPÇ002','OSPÇ00','PINÇA ER 2','UNIDAD','PINÇ','SANDVI','NUL','PI 01-D-','ATIV',25,2,'ROTATIVO 0' ,0
UNION ALL SELECT 3954,'OSPÇ002','OSPÇ00','PINÇA ER 2','UNIDAD','PINÇ','SANDVI','NUL','PI 01-D-','ATIV',25,2,'REFORMA  0' ,0
UNION ALL SELECT 3954,'OSPÇ002','OSPÇ00','PINÇA ER 2','UNIDAD','PINÇ','SANDVI','NUL','PI 01-D-','ATIV',25,2,'EMPRÉSTIMO' ,1
)
SELECT
  ID
, PartNumber
, Codigo
, Descricao
, Unidade
, Familia
, Fabricante
, Modelo
, Local
, Situacao
, Preco
, Saldo
, SUM(CASE Estoque WHEN 'CENTRAL'    THEN Quantidade END) AS "CENTRAL"   
, SUM(CASE Estoque WHEN 'ROTATIVO 0' THEN Quantidade END) AS "ROTATIVO 0"
, SUM(CASE Estoque WHEN 'REFORMA  0' THEN Quantidade END) AS "REFORMA  0"
, SUM(CASE Estoque WHEN 'EMPRÉSTIMO' THEN Quantidade END) AS "EMPRÉSTIMO"
FROM initial_query_output
GROUP BY
  ID
, PartNumber
, Codigo
, Descricao
, Unidade
, Familia
, Fabricante
, Modelo
, Local
, Situacao
, Preco
, Saldo
;

ID   |PartNumber|Codigo|Descricao |Unidade|Familia|Fabricante|Modelo|Local   |Situacao|Preco|Saldo|CENTRAL|ROTATIVO 0|REFORMA  0|EMPRÉSTIMO
3,954|OSPÇ002   |OSPÇ00|PINÇA ER 2|UNIDAD |PINÇ   |SANDVI    |NUL   |PI 01-D-|ATIV    |   25|    2|      1|         0|         0|         1

答案 2 :(得分:0)

我假设第一个子查询只返回每个[Easytool_data].[dbo].[estoque].[id]一行,如果不是,你必须GRUP BY子查询中的每个字段。

WITH Cmd As
(
    SELECT [Easytool_data].[dbo].[estoque].[id] AS ID
          ,[Easytool_data].[dbo].[estoque].[barras] AS PartNumber
          ,[Easytool_data].[dbo].[estoque].[codigo] AS Codigo
          ,[Easytool_data].[dbo].[estoque].[descricao] AS Descricao
          ,[Easytool_data].[dbo].[estoque].[um] AS Unidade
          ,[Easytool_data].[dbo].[familias].[Descricao] AS Familia
          ,[Easytool_data].[dbo].[estoque].[fabricante] AS Fabricante
          ,[Easytool_data].[dbo].[estoque].[modelo] AS Modelo
          ,[Easytool_data].[dbo].[estoque].[armazenagem] AS Local
          ,[Easytool_data].[dbo].[status].[Descricao] AS Situacao
          ,[Easytool_data].[dbo].[estoque].[custo] AS Preco
          ,[Easytool_data].[dbo].[estoque].[sd_atual] AS Saldo
    FROM [Easytool_data].[dbo].[estoque] 
    INNER JOIN [Easytool_data].[dbo].[familias]       
    ON [Easytool_data].[dbo].[estoque].[id_familia] = [Easytool_data].[dbo].[familias].[Id]
    INNER JOIN [Easytool_data].[dbo].[status]
    ON [Easytool_data].[dbo].[estoque].[id_status] = [Easytool_data].[dbo].[status].[Id]
    WHERE  [Easytool_data].[dbo].[estoque].[id] = 3954
)
SELECT ID, PartNumber, Codigo, Descricao, Unidade, Familia, Fabricante, Modelo
       , Local, Situacao, Preco, Saldo,
       CASE WHEN [Easytool_data].[dbo].[local_estoque].[descricao] = 'CENTRAL' 
            THEN [Easytool_data].[dbo].[local_estocado].[quantidade]
            ELSE 0 END AS CENTRAL, 
       CASE WHEN [Easytool_data].[dbo].[local_estoque].[descricao] = 'ROTATIVO' 
            THEN [Easytool_data].[dbo].[local_estocado].[quantidade]
            ELSE 0 END AS ROTATIVO, 
       CASE WHEN [Easytool_data].[dbo].[local_estoque].[descricao] = 'REFORMA' 
            THEN [Easytool_data].[dbo].[local_estocado].[quantidade]
            ELSE 0 END AS REFORMA, 
       CASE WHEN [Easytool_data].[dbo].[local_estoque].[descricao] = 'EMPRÉSTIMO' 
            THEN [Easytool_data].[dbo].[local_estocado].[quantidade]
            ELSE 0 END AS EMPReSTIMO 
FROM Cmd
    INNER JOIN [Easytool_data].[dbo].[local_estoque]
    ON Cmd.[id_local_estoque] = [Easytool_data].[dbo].[local_estoque].[id];
    INNER JOIN [Easytool_data].[dbo].[local_estocado]
    ON [Easytool_data].[dbo].[local_estocado].[id_estoque] = Cmd.Id;