繁体   English   中英

sql一个表的两列引用另一表的同一列

[英]sql Two columns of one table references to the same column of the other table

我有两个表表:cost1_id不为null且cost2_id为可为null的产品

   id    | cost1_id | cost2_id
   1     | 1        | 2
   2     | 3        | 

表:费用

   id    | value    | currency
   1     | 15       | EUR
   2     | 20       | USD
   3     | 100      | TND

我想在不使用连接的情况下获得此结果(我宁愿使用UNION,因为我的数据库很大)

product_id | cost1_value | cost1_currency | cost2_value | cost2_currency 
     1     | 15          | EUR            |  20         |  USD
     2     | 100         | TND            |             |

我可以想到的最小化连接的一种选择是...

SELECT
    product.id    AS product_id,
    MAX(CASE WHEN cost.id = product.cost1_id THEN cost.value    END)   AS cost1_value,
    MAX(CASE WHEN cost.id = product.cost1_id THEN cost.currency END)   AS cost1_currency,
    MAX(CASE WHEN cost.id = product.cost2_id THEN cost.value    END)   AS cost2_value,
    MAX(CASE WHEN cost.id = product.cost2_id THEN cost.currency END)   AS cost2_currency
FROM
    product
LEFT JOIN
    cost
        ON cost.id IN (product.cost1_id, product.cost2_id)
GROUP BY
    product.id

就是说,使用IN()可能会比仅加入两次更慢...


确保您的表上有索引。 它们是优化联接的方法,而不是避免它们的方法...

  • 在这种情况下,您可能只需要在Cost表中使用集群主键即可。

因此,我强烈建议您至少 尝试执行此操作的“常规”方式...

SELECT
    product.id    AS product_id,
    c1.value      AS cost1_value,
    c1.currency   AS cost1_currency,
    c2.value      AS cost2_value,
    c2.currency   AS cost2_currency
FROM
    product
LEFT JOIN
    cost    c1
        ON c1.id = product.cost1_id
LEFT JOIN
    cost    c2
        ON c2.id = product.cost2_id

编辑:

另一个深奥的选择可能是...

SELECT
    product_id,
    MAX(cost1_value)       AS cost1_value,
    MAX(cost1_currency)    AS cost1_currency,
    MAX(cost2_value)       AS cost2_value,
    MAX(cost2_currency)    AS cost2_currency
FROM
(
    SELECT
        product.id                                       AS product_id,
        cost.value                                       AS cost1_value,
        cost.currency                                    AS cost1_currency,
        CASE WHEN 1=0 THEN cost.value    ELSE NULL END   AS cost2_value,
        CASE WHEN 1=0 THEN cost.currency ELSE NULL END   AS cost2_currency
    FROM
        product
    LEFT JOIN
        cost
            ON cost.id = product.cost1_id

    UNION ALL

    SELECT
        product.id                                       AS product_id,
        NULL                                             AS cost1_value,
        NULL                                             AS cost1_currency,
        cost.value                                       AS cost2_value,
        cost.currency                                    AS cost2_currency
    FROM
        product
    INNER JOIN
        cost
            ON cost.id = product.cost2_id
)
    unioned
GROUP BY
    product_id

然后创建这些索引...

CREATE INDEX ix_product_cost1 ON product(cost1_id, id);
CREATE INDEX ix_product_cost2 ON product(cost2_id, id);

可能会稍快一些,但是以显着增加复杂性为代价,这在将来成为维护的头疼问题。

试试这个答案,这个答案是针对SQL Server PostgreSQL尝试相同的方法。

CREATE table #Product(ID INT,Cost1_id INT,Cost2_id INT)
INSERT INTO #Product VALUES(1,1,1)
INSERT INTO #Product VALUES(2,3,0)

CREATE table #Cost(ID INT,Value INT,currency VARCHAR(10))
INSERT INTO #Cost VALUES(1,15,'EUR')
INSERT INTO #Cost VALUES(2,20,'USD')
INSERT INTO #Cost VALUES(3,100,'TND')

SELECT ID product_id,MAX(cost1_value)cost1_value,MAX(cost1_Currency)cost1_Currency
        ,MAX(cost2_value)cost2_value,MAX(cost2_Currency)cost2_Currency
FROM(
    SELECT P.ID,C.Value cost1_value,C.Currency cost1_Currency,0 AS cost2_value,'' AS cost2_Currency
    from #Cost C, #Product P
    WHERE P.Cost1_id=C.Id
    UNION ALL
    SELECT P.ID,0 AS cost2_value,'' AS cost2_Currency,C.Value ,C.Currency 
    from #Cost C, #Product P
    WHERE P.Cost2_id=C.Id
    )D
GROUP BY ID

希望这对您有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM