【问题标题】:Select only rows without other occurrence type仅选择没有其他出现类型的行
【发布时间】:2019-12-14 00:04:30
【问题描述】:

我不知道如何解释这个问题,所以让我尝试一个简化的例子。

我有两个表 TicketsTicketEntities

门票

tID | Customer |  Val
----|----------|------
1   | Paul     |  20
2   | Paul     |  10
3   | Peter    |  15
4   | Jane     |  100
5   | Doe      |  400
6   | John     |  5

TicketEntities

EntityID |  TicketID |   Type
---------|-----------|--------
1        |   1       |   1     
2        |   1       |   2
3        |   3       |   1
4        |   4       |   1
5        |   5       |   2
6        |   6       |   2

我想创建两个视图(如果可以的话,最好是这样):

  1. [已解决] 查看 TicketEntity 类型 1 的票证。我的工作解决方案: 期望的结果:

    tID   |   Customer  | Val | EntityID |  Type
    

    -------|-------------|-----|---------|------- 1 |保罗 | 20 | 1 | 1 3 |彼得 | 15 | 3 | 1 4 |简 | 100 | 4 | 1

    注意:不是实际的查询/结果

    SQL

    SELECT *
    FROM Tickets AS t
    LEFT JOIN TicketEntities AS e ON t.ID=e.TicketID WHERE e.EntityTypeId = 1 
    
  2. 仅查看 TicketEntity 类型为 2 而不是 1 的工单

    期望的结果:

    tID   |   Customer  | Val | EntityID |  Type
    ------|-------------|-----|----------|-------
    5     |     Doe     | 400 |  5       |   2
    6     |     John    | 5   |  6       |   2   
    

    SQL

    SELECT *
      FROM Tickets AS t
      LEFT JOIN TicketEntities AS e ON t.ID=e.TicketID WHERE e.EntityTypeId = 1 
    AND 
    NOT EXISTS (SELECT * 
      FROM dbo.Tickets AS t2
        INNER JOIN dbo.TicketEntities AS e2 ON t2.Id=e2.Ticket_Id 
        WHERE e2.EntityTypeId = 2)
    
  3. 或者更优选地,单一视图:

    期望的结果:

    tID    |    Customer |  Val |  Entity_Type1 |  Entity_Type2
    -------|-------------|------|---------------|---------------
    1      |    Paul     |  20  |  1            |  2
    2      |    Paul     |  10  |               |
    3      |    Peter    |  15  |  1            |    
    4      |    Jane     |  100 |  1            |    
    5      |    Doe      |  400 |               |  2
    6      |    John     |  5   |               |  2  
    

    SQL

    我不知道该怎么做。自行加入?

最后,欢迎对问题进行改进。解决这个问题的最佳方法是什么?

【问题讨论】:

  • 您的 LEFT JOIN 返回常规的 INNER JOIN 结果。将 e.EntityTypeId 条件从 WHERE 移动到 ON 以获得真正的 LEFT JOIN 结果。

标签: sql sql-server join left-join


【解决方案1】:

我认为从Tickets 表到TicketEntities 表的两个左连接应该在这里工作:

SELECT
    t.tID,
    t.Customer,
    t.Val,
    te1.Type,
    te2.Type
FROM Tickets t
LEFT JOIN TicketEntities te1
    ON t.tID = te1.TicketID AND te1.Type = 1
LEFT JOIN TicketEntities te2
    ON t.tID = te2.TicketID AND te2.Type = 2;

Demo

请注意,我们不会对两个 TicketEntities 连接施加任何 WHERE 限制。这是为了确保我们不会过早过滤掉任何票证记录。

【讨论】:

  • 哇。这行得通!我将其标记为简单的解决方案。
【解决方案2】:

试试这个。由于您已经有了数据,因此简单的左连接与票证主表将根据您的需要提供所需的结果。

; WITH CT1 AS (
    SELECT *
    FROM Tickets AS t
    LEFT JOIN TicketEntities AS e ON t.ID=e.TicketID WHERE e.EntityTypeId = 1 
), 
CT2 AS (
    SELECT *
      FROM Tickets AS t
      LEFT JOIN TicketEntities AS e ON t.ID=e.TicketID WHERE e.EntityTypeId = 1 
    AND 
    NOT EXISTS (SELECT * 
      FROM dbo.Tickets AS t2
        INNER JOIN dbo.TicketEntities AS e2 ON t2.Id=e2.Ticket_Id 
        WHERE e2.EntityTypeId = 2)
)
SELECT TICKET.ID, TICKET.CUSTOMER, 
      CASE WHEN ISNULL(CT1.EntityID,'')='' THEN CT2.VAL ELSE CT1.VAL END AS VAL,
      ISNULL(CT1.EntityID,'') AS ENTRY_TYPE1, ISNULL(CT2.EntityID,'') AS ENTRY_TYPE1
FROM TICKETS AS TICKET 
LEFT JOIN CT1 ON TICKET.ID=CT1.ID
LEFT JOIN CT2 ON TICKET.ID=CT2.ID

【讨论】:

    【解决方案3】:

    一个查询多个 [Type] 值。让我们尝试枢轴功能。考虑您必须使用聚合函数对行进行分组。查询可能如下所示:

    WITH CTE AS (
       SELECT
          T.tID,
          T.Customer,
          T.Val,
          TS.Type 
       FROM
          dbo.Tickets T
          LEFT JOIN dbo.TicketEntities TS ON T.tID = TS.TicketID   
    )
    SELECT *
    FROM
       CTE
       PIVOT (Max(Type) FOR Type IN ([1], [2])) P
    

    您可以扩展此查询,用 select 替换 ([1], [2])。见:SQL PIVOT SELECT FROM LIST (IN SELECT)

    【讨论】:

      猜你喜欢
      • 2019-05-23
      • 1970-01-01
      • 1970-01-01
      • 2017-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-13
      • 1970-01-01
      相关资源
      最近更新 更多