【问题标题】:Correlated subqueries: How to get the ID of the outer query?相关子查询:如何获取外部查询的 ID?
【发布时间】:2015-06-01 07:45:32
【问题描述】:

我有多个表:

Person
---------------------
IDPerson, Name

StickerTransaction
---------------------
IDTransac, IDPerson, IDSomeoneElse, NbStickersReceived, NbStickersGiven

Purchase
---------------------
IDPurchase, IDPerson, NbStickersBought

我正在尝试让每个从未进行过交易或目前拥有 0 个贴纸的人。要获得一个人拥有的贴纸数量,公式如下:

NbStickersBought + NbStickersReceived - NbStickersGiven

这是我目前收到的查询。我遇到的问题是在子子查询中......我无权访问此人的 ID。

有没有办法访问这个人的 ID,或者有没有更好的方法来编写这个查询?

SELECT People.IDPerson, People.Name
FROM
(
    -- Selects people that never made a sticker transaction

    SELECT p.IDPerson, p.Name
    FROM Person p
    LEFT JOIN StickerTransaction sT
    ON p.IDPerson = sT.IDPerson
    WHERE sT.IDPerson IS NULL

    UNION

    -- Selects people that have currently 0 sticker

    SELECT p.IDPerson, p.Name
    FROM Person p
    WHERE 0 = (
                SELECT SUM(NbStickers) AS NbStickers
                FROM (

                       -- I do not have access to p.IDPerson here...

                       SELECT (sT.NbStickersReceived - sT.NbStickersGiven) AS NbStickers
                       FROM StickerTransaction sT
                       WHERE sT.IDPerson = p.IDPerson

                     UNION ALL

                       -- I do not have access to p.IDPerson here either...

                       SELECT pu.NbStickersBought AS NbStickers
                       FROM Purchase pu
                       WHERE pu.IDPerson = p.IDPerson
                     )
              )
) People

【问题讨论】:

  • 您使用的是哪种 dbms 产品?子查询应该可以访问其外部查询的 p.IDPerson。
  • 我用的是HFSQL,WinDev自带的DBMS。

标签: sql sum subquery correlated-subquery


【解决方案1】:

AFAIK 你不能对派生表进行关联。但是您可以将查询重写为不相关的子查询:

SELECT People.IDPerson, People.NAME
FROM
(
    -- Selects people that never made a sticker transaction

    SELECT p.IDPerson, p.NAME
    FROM Person p
    LEFT JOIN StickerTransaction sT
    ON p.IDPerson = sT.IDPerson
    WHERE sT.IDPerson IS NULL

    UNION

    -- Selects people that have currently 0 sticker

    SELECT p.IDPerson, p.NAME
    FROM Person p
    JOIN     (
                SELECT sT.IDPerson, SUM(NbStickers) AS NbStickers
                FROM (

                       SELECT (sT.NbStickersReceived - sT.NbStickersGiven) AS NbStickers
                       FROM StickerTransaction sT

                     UNION ALL

                       SELECT pu.NbStickersBought AS NbStickers
                       FROM Purchase pu
                     ) dt
                GROUP BY sT.IDPerson
                HAVING SUM(NbStickers) = 0
             ) sT
    ON sT.IDPerson = p.IDPerson

) People

【讨论】:

    【解决方案2】:
    SELECT People.IDPerson, People.Name
    FROM Person 
    where IDPerson not in 
       (select distinct IDPerson from StickerTransaction)
    and IDPerson not in 
       (SELECT IDPerson from Purchase group by IDPerson having SUM(NbStickers) > 0)
    

    【讨论】:

      【解决方案3】:

      使用NOT EXISTS 查找从未购买过的人。

      使用另一个子查询查找具有与 NbStickersGiven 相同数量的 NbStickersReceived 的人。

      SELECT p.IDPerson, p.Name
      FROM Person p
      where not exists (select 1 from Purchase
                        where IDPerson = p.IDPerson)
         or 0 = (select sum(NbStickersReceived) - sum(NbStickersGiven)
                 from StickerTransaction
                 where IDPerson = p.IDPerson)
      

      也许您需要在第二个子查询附近使用 COALESCE 来处理没有任何 StickerTransactions 的人。

      【讨论】:

        【解决方案4】:

        您必须在外部语句中创建链接。

        -- Selects people that have currently 0 sticker
        SELECT p.IDPerson, p.Name
         FROM Person p,
         (SELECT sT.IDPerson, SUM(NbStickers) sum_stickers
            FROM ((SELECT sT.IDPerson, (sT.NbStickersReceived - sT.NbStickersGiven) AS NbStickers
         FROM StickerTransaction sT)
        UNION
        (SELECT pu.IDPerson, pu.NbStickersBought AS NbStickers
          FROM PURCHASE pu
          ))
         group by sT.IDPerson
        ) zeroSticker
        where zeroSticker.IDPerson = p.IDPerson and zeroSticker.sum_stickers = 0
        

        因为在纯 SQL 中不可能将参数注入子查询。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多