简体   繁体   English

SQL子查询与UNION ALL查询结合

[英]SQL subquery combine with UNION ALL query

I have two tables: goods with column id and cost and good_texts with columns goodid, languageid, title. 我有两个表:具有ID和Cost列的商品,以及具有goodid,languageid,title列的good_texts。 So good_texts contains translations for good. 所以good_texts包含翻译。

I have query that selects title for current language if it available and selects default title if it is not available for one good: 我有一个查询,如果可用,选择当前语言的标题,如果不可用,则选择默认标题:

    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
    )

This works fine and returns only one row. 这可以正常工作,并且只返回一行。 Now I'm trying to write query to get all data from good table as well as title from good_texts table. 现在,我尝试编写查询以从良好表中获取所有数据以及从good_texts表中获得标题。 I'm trying to do this using this query: 我正在尝试使用以下查询执行此操作:

    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

But this doesn't work with error 但这不会出错

more than one row returned by a subquery used as an expression 子查询返回的多于一行用作表达式

I can't understand why my subquery returns more than one row even so it returns one row if it runs separately. 我不明白为什么我的子查询甚至返回多行,因此如果单独运行它会返回一行。 How my goal can be achieved? 我的目标如何实现?

The query that you want looks like this: 您想要的查询如下所示:

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
                 );

The first gets everything with language id "2". 第一个获取的语言ID为“ 2”的所有内容。 The second gets all goods who have language id "1" but not "2". 第二个将获取所有语言标识为“ 1”但不为“ 2”的商品。

In Postgres, this is more easily done using DISTINCT ON : 在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);

The condition are not the same 条件不一样

in working one query is 在工作一个查询是

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

and in the not working one is 而在不工作的是

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

You select different column goodid and title in subquery in NOT in clause .. 您在子句中的子查询中的..中选择了不同的列goodidtitle

The select statement expects to operate over one row of data. select语句期望对一行数据进行操作。 The from and where clauses will determine how many rows of data the query returns (other things can as well but in an effort to keep it simple we can ignore those here). from和where子句将确定查询返回的数据行数(其他情况也可以,但是为了保持简单性,我们可以在此处忽略这些行)。

Basically you are asking the database to select something and then in one of the fields in your select statement you are trying to again select something that returns more than 1 row, which causes the error. 基本上,您是在要求数据库选择某些内容,然后在select语句的一个字段中尝试重新选择返回多于1行的内容,这会导致错误。

You need to change your logic to use joins instead of sub selects. 您需要更改逻辑以使用联接而不是子选择。

On mobile so can't provide code examples right now. 在移动设备上,因此目前无法提供代码示例。

I've managed to resolve the issue using @Gordon Linoff code and final result was: 我设法使用@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
                 )

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

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