带连接和透视的SQL

带连接和透视的SQL,sql,sql-server,tsql,Sql,Sql Server,Tsql,今天我花了6个多小时试图找到这个SQL解决方案,但没有成功。老实说,经过一些搜索,我发现我必须使用PIVOT指令(以前从未见过它)才能得到我想要的东西,从那时起,我一直在尝试找出这个命令在与join命令一起使用时的含义。我不是那么聪明 这就是我想要做的: 我有这些表(我正在展示我认为与这个问题相关的表,因为还有一些其他的内部联接引用其他表): 此查询: SELECT [Easytool_data].[dbo].[estoque].[id] AS ID ,[Easytool_

今天我花了6个多小时试图找到这个SQL解决方案,但没有成功。老实说,经过一些搜索,我发现我必须使用PIVOT指令(以前从未见过它)才能得到我想要的东西,从那时起,我一直在尝试找出这个命令在与join命令一起使用时的含义。我不是那么聪明

这就是我想要做的:

我有这些表(我正在展示我认为与这个问题相关的表,因为还有一些其他的内部联接引用其他表):



此查询:

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来实现这一点,但我完全不知道如何将它与几个内部连接命令(如查询中的一个)结合使用。我试过几种不同的方法,但总是出错

有谁能给我举个例子,说明在使用类似于我的查询之后,我如何实现我的目标

我在黑板上搜索了一下,发现所有的例子与我的查询相比都太复杂或太简单了。我并不懒惰,我愿意尽我最大的努力来学习这一点,但现在看来这是遥不可及的

如果有人能给我点启示我会非常感激

多谢各位
Daniel

我假设第一个子查询仅通过每个
[Easytool_data].[dbo].[estoque].[id]
返回一行,否则必须通过子查询中的每个字段进行GRUP

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;

我假设第一个子查询仅通过每个
[Easytool_data].[dbo].[estoque].[id]
返回一行,否则必须按子查询中的每个字段进行GRUP

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;

如果用上面的查询替换我称之为
initial\u query\u output
的fullselect公共表表达式,这应该可以工作:

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

如果用上面的查询替换我称之为
initial\u query\u output
的fullselect公共表表达式,这应该可以工作:

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

仅使用SQL进行水平数据透视通常是关于使用一个描述性的、以前是垂直的列;与用于大小写表达式的名称相同,用作列名。 像这样:


仅使用SQL进行水平数据透视通常是关于使用一个描述性的、以前是垂直的列;与用于大小写表达式的名称相同,用作列名。 像这样:


PIVOT用于聚合值如果使用表别名,则语法会少得多。将此
[Easytool_data].[dbo].[estoque]esto
用于更改引用其他地方,如
[Easytool_data].[dbo].[estoque].[id]AS id
esto.id AS id
枢轴用于聚合值如果使用表别名,则语法会少得多。将此
[Easytool_data].[dbo].[estoque]esto
用于更改其他引用,如
[Easytool_data].[dbo].[estoque].[id]AS id
esto.id AS id
立即尝试。很抱歉,我有点累了,3个表用于cte查询,2个表用于第二个子查询。我尝试使用您的最新代码,但发现以下错误:-我将代码更改为如下:-现在我没有收到错误,但数据也无法检索。一无所获。我检查了所有连接,它们是有意义的。这是数据库备份:(30mb)-你看到我的代码中有任何明显的错误吗?现在就试试。很抱歉,我有点累了,3个表用于cte查询,2个表用于第二个子查询。我尝试使用您的最新代码,但发现以下错误:-我将代码更改为如下:-现在我没有收到错误,但数据也无法检索。一无所获。我检查了所有连接,它们是有意义的。这是数据库备份:(30mb)-你看到我的代码中有任何明显的错误吗?它成功了!我现在将尝试删除额外的列,并使数量显示在行“CENTRAL”、“REFORMA”的下方。。。。还不确定我是否能做到,但值得一试!谢谢@Marcothesane我会发布第二个答案。这是我从一开始就应该做的。等几秒钟……它成功了!我现在将尝试删除额外的列,并使数量显示在行“CENTRAL”、“REFORMA”的下方。。。。还不确定我是否能做到,但值得一试!谢谢@Marcothesane我会发布第二个答案。这是我从一开始就应该做的。等几秒钟……这个看起来更好!再次感谢你!这个看起来更好!再次感谢你!