SQL子查询与UNION ALL查询

时间:2016-07-24 10:36:12

标签: mysql sql postgresql

我有两个表:具有列ID和成本的商品以及具有列goodid,languageid,title的good_texts。所以good_texts包含好的翻译。

我有查询,如果可用,则选择当前语言的标题,如果一个商品不可用,则选择默认标题:

    SELECT
    *
FROM
    good_texts
WHERE
    languageid = 2
UNION ALL
    SELECT
        *
    FROM
        good_texts
    WHERE
        languageid = 1 AND goodid = 92
    AND goodid NOT IN (
        SELECT
            goodid
        FROM
            good_texts
        WHERE
            languageid = 2 and goodid = 92
    )

这很好,只返回一行。 现在我正在尝试编写查询以从good_texts表中获取好表和标题的所有数据。 我正在尝试使用此查询执行此操作:

    SELECT
    s1.id,
    s1.cost,
    (SELECT
    s2.title
FROM
    good_texts s2
WHERE
    languageid = 2
UNION ALL
    SELECT
        s3.title
    FROM
        good_texts s3
    WHERE
        languageid = 1 AND s3.goodid = s1.id
    AND s3.goodid NOT IN (
        SELECT
            s4.goodid
        FROM
            good_texts s4
        WHERE
            languageid = 2 AND s4.goodid = s1.id
    ))
FROM
    goods s1

但这不适用于错误

  

用作表达式

的子查询返回的多行

我无法理解为什么我的子查询返回多行,即使它单独运行也会返回一行。 我的目标如何实现?

4 个答案:

答案 0 :(得分:2)

您想要的查询如下所示:

SELECT gt.*
FROM good_texts gt
WHERE gt.languageid = 2
UNION ALL
SELECT gt.*
FROM good_texts gt
WHERE gt.languageid = 1 AND
      NOT EXISTS (SELECT 1
                  FROM good_texts gt2
                  WHERE gt2.goodid = gt.goodid AND gt2.languageid = 2
                 );

第一个用语言ID" 2"来获取所有内容。第二个获得所有具有语言ID" 1"但不是" 2"。

在Postgres中,使用DISTINCT ON

可以更轻松地完成此操作
SELECT DISTINCT ON (gt.goodid) gt.*
FROM good_texts gt
WHERE gt.languageid IN (1, 2)
ORDER BY gt.goodid, (CASE WHEN gt.languageid = 2 THEN 1 ELSE 2 END);

答案 1 :(得分:0)

条件不一样

在处理一个查询时

    AND goodid NOT IN (
    SELECT
        goodid
    FROM
        good_texts
    WHERE
        languageid = 2 and goodid = 92
)

并且在不工作的是

AND title NOT IN (
    SELECT
        title
    FROM
        good_texts s4
    WHERE
        languageid = 2 AND s4.goodid = s1.id
)

您在NOT in子句中的子查询中选择了不同的列goodidtitle

答案 2 :(得分:0)

select语句需要在一行数据上运行。 from和where子句将确定查询返回多少行数据(其他事情也可以,但为了保持简单,我们可以忽略这些)。

基本上,您要求数据库选择一些内容,然后在select语句的某个字段中,您尝试再次选择返回多于1行的内容,这会导致错误。

您需要更改逻辑以使用连接而不是子选择。

在移动设备上,所以现在无法提供代码示例。

答案 3 :(得分:0)

我设法使用@Gordon Linoff代码解决了这个问题,最终结果是:

SELECT gt.*, goods.*
FROM good_texts gt
JOIN goods ON goods.id = gt.goodid
WHERE gt.languageid = 2
UNION ALL
SELECT gt.*, goods.*
FROM good_texts gt
JOIN goods ON goods.id = gt.goodid
WHERE gt.languageid = 1 AND
      NOT EXISTS (SELECT 1
                  FROM good_texts gt2
                  WHERE gt2.goodid = gt.goodid AND gt2.languageid = 2
                 )