【问题标题】:Union Columns Vertically in SQLSQL中的垂直联合列
【发布时间】:2020-05-06 02:56:20
【问题描述】:

假设这些表:

群组:(ID、标题):{1,G1}, {2,G2}, {3,G3}, {4, G4}

类别:(ID、标题):{1, Cat1}, {2, Cat2}, {3, Cat3}, {4, Cat4}

产品:(Id、GroupId、CategoryId、名称):

{1, 1, 1, G1C1P1},
{2, 1, 2, G1C2P2},
{3, 1, 2, G1C2P3},
{4, 2, 2, G2C2P4},
{5, 2, 2, G2C2P5},
{6, 3, 1, G3C1P6},
{7, 3, 3, G3C3P7}

经销商:(ID、姓名):{1, 'Dealer1'}, {2, 'Dealer2'}, {3, 'Dealer3'}

ProductDealer(Id、ProductId(英国)、DealerId、LastSale、编号):

{1, 1, 1, 5, '2012-12-10 12:34:31'}, 
{2, 2, 2, 120, '2012-11-10 12:34:31'}, 
{3, 5, 1, 75, '2012-12-02 12:34:31'}

所以我要创建一个完整的产品视图,这是我的第一次尝试:

SELECT 
    [PR].[Id],
    [PR].[Name],
    [PR].[GroupId],
    [GR].[Title] AS [Group],
    [PR].[CategoryId],
    [CA].[Title] AS [Category]

FROM [dbo].[Product] AS [PR]
INNER JOIN [dbo].[Group] AS [GR] ON [PR].[GroupId] = [GR].[Id]
INNER JOIN [dbo].[Category] AS [CA] ON [PR].[CategoryId] = [CA].[Id]

然后我想添加ProductDealer列来查看,所以我试试这个:

SELECT 
    [PR].[Id],
    [PR].[Name],
    [PR].[GroupId],
    [GR].[Title] AS [Group],
    [PR].[CategoryId],
    [CA].[Title] AS [Category],
    ISNULL(
    (SELECT [PD].[Id] FROM [dbo].[ProductDealer] AS [PD] 
     WHERE [PD].[ProductId] = [PR].[Id]),
     CAST(-1 AS BIGINT)
    ) AS [ProductDealerId],
    ISNULL(
    (SELECT [DE].[Id] FROM [dbo].[Dealer] AS [DE]
    INNER JOIN [dbo].[ProductDealer] AS [PD] ON [DE].[Id] = [PD].[DealerId]
     WHERE [PD].[ProductId] = [PR].[Id]),
     CAST(-1 AS BIGINT)
    ) AS [DealerId],
     ISNULL(
    (SELECT [DE].[Name] FROM [dbo].[Dealer] AS [DE]
    INNER JOIN [dbo].[ProductDealer] AS [PD] ON [DE].[Id] = [PD].[DealerId]
     WHERE [PD].[ProductId] = [PR].[Id]),
     CAST('HaveNotDealer' AS NVARCHAR)
    ) AS [Dealer],
    ISNULL(
    (SELECT [PD].[LastSale] FROM [dbo].[ProductDealer] AS [PD] 
     WHERE [PD].[ProductId] = [PR].[Id]),
    CAST('0001-01-01 00:00:01' AS DATETIME2)
    ) AS [LastSale],
    ISNULL(
    (SELECT [PD].[Number] FROM [dbo].[ProductDealer] AS [PD] 
     WHERE [PD].[ProductId] = [PR].[Id]),
    CAST(0 AS BIGINT)
    ) AS [SaleNumber]

FROM [dbo].[Product] AS [PR]
INNER JOIN [dbo].[Group] AS [GR] ON [PR].[GroupId] = [GR].[Id]
INNER JOIN [dbo].[Category] AS [CA] ON [PR].[CategoryId] = [CA].[Id]

正如您在ProductDealer 中看到的每一列我写了一个完整的选择查询我不知道有没有更好的方法来做到这一点?类似于将此列合并到第一个视图,您有什么建议最好地实施它?

更新

ProductDealer 表中,ProductId 是英国,因此每个产品可以有一个经销商或没有经销商,如果产品有经销商,我希望查看 ProductDealer 列,如果没有,则获取我的默认值,例如: (-1, 'HaveNotDealer')。

【问题讨论】:

  • 你需要更清楚你想要达到的目标。是否对于每种产品,您都希望将该产品的每个经销商的详细信息附加到最后一列和销售数量(或其他一些摘要)?或者您是否想要类似 [产品栏] [第一个经销商的专栏] [第二个经销商的专栏] [...] - 如果是这种情况,那么我建议如果可能的话,最好在您的表示层中完成。跨度>
  • @Ian Yates 在ProductDealer 表中ProductId 是英国,所以每个产品可以有一个经销商或没有,如果产品有经销商,我希望得到ProductDealer 列,如果没有获取我的默认值,例如:(-1, 'HaveNotDealer')

标签: sql sql-server sql-server-2008 tsql


【解决方案1】:
SELECT 
    [PR].[Id],
    [PR].[Name],
    [PR].[GroupId],
    [GR].[Title] AS [Group],
    [PR].[CategoryId],
    [CA].[Title] AS [Category],
    ISNULL([PD].[Id],
    CAST(-1 AS BIGINT)) AS [ProductDealerId],
    ISNULL([D].Id,
    CAST(-1 AS BIGINT)) as DealerId,
    ISNULL([D].Name,
    CAST('HaveNotDealer' AS NVARCHAR)) as DealerName,
    ISNULL(PD.LastSale,
    CAST('0001-01-01 00:00:01' AS DATETIME2)) as LastSale,
    ISNULL([PD].Number,
    CAST(0 AS BIGINT)) as SaleNumber

FROM [dbo].[Product] AS [PR]
INNER JOIN [dbo].[Group] AS [GR] ON [PR].[GroupId] = [GR].[Id]
INNER JOIN [dbo].[Category] AS [CA] ON [PR].[CategoryId] = [CA].[Id]
LEFT OUTER JOIN [dbo].[ProductDealer] AS [PD] ON [PR].[Id] = [PD].[ProductId]
LEFT OUTER JOIN [dbo].[Dealer] AS [D] ON [PD].DealerId = [D].Id

【讨论】:

    【解决方案2】:

    也许只是在“精神”中回答这个问题,但这是我偶然发现这个问题时正在寻找的“垂直联合列”答案=)

    with aa(col1, col2) as (
        select * from (values (1,2) ) blah
    ),
     bb(col3, col4) as (
        select * from (values (5,6) ) blah
    )
    
    select select aa.col1, aa.col2, bb.col3, bb.col4
    from aa , bb
    

    给予

    col1|col2|col3|col4
    1   |2   |5   |6   
    

    免责声明以上仅适用于单行aabb

    【讨论】:

      【解决方案3】:

      这里是“垂直 UNION”版本:

      WITH "Group"
           AS
           (
            SELECT * 
              FROM (
                    VALUES (1,'G1'), (2,'G2'), (3,'G3'), (4, 'G4')
                   ) AS T (Id, Title)
           ),
           Category
           AS
           (
            SELECT * 
              FROM (
                    VALUES (1, 'Cat1'), (2, 'Cat2'), (3, 'Cat3'), (4, 'Cat4')
                   ) AS T (Id, Title)
           ),
           Product
           AS
           (
            SELECT * 
              FROM (
                    VALUES (1, 1, 1, 'G1C1P1'),
                           (2, 1, 2, 'G1C2P2'),
                           (3, 1, 2, 'G1C2P3'),
                           (4, 2, 2, 'G2C2P4'),
                           (5, 2, 2, 'G2C2P5'),
                           (6, 3, 1, 'G3C1P6'),
                           (7, 3, 3, 'G3C3P7')
                   ) AS T (Id, GroupId, CategoryId, Name)
           ),
           Dealer
           AS
           (
            SELECT * 
              FROM (
                    VALUES (1, 'Dealer1'), (2, 'Dealer2'), (3, 'Dealer3')
                   ) AS T (Id, Name)
           ),
           ProductDealer 
           AS
           (
            SELECT *
              FROM (
                    VALUES (1, 1, 1, 5, '2012-12-10 12:34:31'), 
                           (2, 2, 2, 120, '2012-11-10 12:34:31'), 
                           (3, 5, 1, 75, '2012-12-02 12:34:31')
                   ) AS T (Id, ProductId, DealerId, Number, LastSale)
           )     
      SELECT PR.Id, PR.Name, PR.GroupId, GR.Title AS "Group",
             PR.CategoryId, CA.Title AS Category, 
             PD.Id AS ProductDealerId,
             D.Id DealerId,
             D.Name AS DealerName,
             PD.LastSale AS LastSale,
             PD.Number AS SaleNumber
        FROM Product AS PR
             JOIN "Group" AS GR ON PR.GroupId = GR.Id
             JOIN Category AS CA ON PR.CategoryId = CA.Id
             JOIN ProductDealer AS PD ON PR.Id = PD.ProductId
             JOIN Dealer AS D ON PD.DealerId = D.Id
      
      UNION
      
      SELECT PR.Id, PR.Name, PR.GroupId, GR.Title AS "Group",
             PR.CategoryId, CA.Title AS Category, 
             PD.Id AS ProductDealerId,
             CAST(-1 AS BIGINT) DealerId,
             CAST('HaveNotDealer' AS NVARCHAR) AS DealerName,
             PD.LastSale AS LastSale,
             PD.Number AS SaleNumber
        FROM Product AS PR
             JOIN "Group" AS GR ON PR.GroupId = GR.Id
             JOIN Category AS CA ON PR.CategoryId = CA.Id
             JOIN ProductDealer AS PD ON PR.Id = PD.ProductId
       WHERE PD.DealerId NOT IN ( SELECT Id FROM Dealer )
      
      UNION
      
      SELECT PR.Id, PR.Name, PR.GroupId, GR.Title AS "Group",
             PR.CategoryId, CA.Title AS Category, 
             CAST(-1 AS BIGINT) AS ProductDealerId,
             CAST(-1 AS BIGINT) DealerId,
             CAST('HaveNotDealer' AS NVARCHAR) AS DealerName,
             CAST('0001-01-01 00:00:01' AS DATETIME2) AS LastSale,
             CAST(0 AS BIGINT) AS SaleNumber
        FROM Product AS PR
             JOIN "Group" AS GR ON PR.GroupId = GR.Id
             JOIN Category AS CA ON PR.CategoryId = CA.Id
       WHERE PR.Id NOT IN ( SELECT ProductId FROM ProductDealer );
      

      【讨论】:

        【解决方案4】:

        像这样:

        SELECT 
            [PR].[Id],
            [PR].[Name],
            [PR].[GroupId],
            [GR].[Title] AS [Group],
            [PR].[CategoryId],
            [CA].[Title] AS [Category],
            PD.ID AS ProductDealerID,
            PD.DealerId,
            DE.Name AS Dealer,
            PD.LastSale,
            PD.Number AS SaleNumber
        
        FROM [dbo].[Product] AS [PR]
        INNER JOIN [dbo].[Group] AS [GR] ON [PR].[GroupId] = [GR].[Id]
        INNER JOIN [dbo].[Category] AS [CA] ON [PR].[CategoryId] = [CA].[Id]
        LEFT JOIN  ProductDealer AS [PD] ON PD.ProductId = PR.ID
        LEFT JOIN  Dealer AS DE ON DE.ID = PD.DealerId
        

        【讨论】:

          猜你喜欢
          • 2020-10-11
          • 2011-02-18
          • 2018-11-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-25
          • 1970-01-01
          相关资源
          最近更新 更多