UNION ALL返回多个结果

时间:2014-05-10 00:53:22

标签: mysql sql

此查询返回多个结果。在底部,您可以看到每个ID号有两个。如何区分我仍然获得25条唯一值记录的记录?

        SELECT *
            FROM(
                SELECT
                    DISTINCT cards.id, cards.name, cards.created_at, cards.updated_at
                    FROM cards
                        INNER JOIN card_process
                            ON card_process.card_id = cards.id
                            INNER JOIN processes
                                ON processes.id = card_process.process_id
                                INNER JOIN category_process
                                    ON category_process.process_id = processes.id
                                    INNER JOIN categories
                                        ON categories.id = category_process.category_id
                                        INNER JOIN series
                                            ON series.id = categories.serie_id
                                            INNER JOIN serie_user
                                                ON serie_user.serie_id = series.id
                        AND `cards`.`type` NOT IN ('', 'libraries')
                        AND NOT `cards`.`deleted`
                        AND NOT `categories`.`deleted`
                        AND NOT `series`.`deleted`
                        AND `cards`.`type` IN ('forms')
                        AND `series`.`id` IN (124,235,126,126,201,236,207,207,207,207,247,234,131,131,221,225,225,222)
            UNION ALL
                SELECT
                    DISTINCT cards.id, cards.name, cards.created_at, cards.updated_at
                    FROM cards
                        WHERE `cards`.`account_user_id`='9'
                            AND NOT `cards`.`deleted`
                            AND `cards`.`type` IN ('forms')
            ) AS qry
                ORDER BY `updated_at` ASC
                LIMIT 0, 25

enter image description here

2 个答案:

答案 0 :(得分:3)

不了解您的架构或数据形状,您可以通过简化查询来获得所需内容。假设一个大致符合标准的SQL方言

  • 您不需要附上select完整选择(联合选择表达式)需要order by,该顺序适用于整个完整选择

  • 您不需要distinctselect个语句的union关键字:union本身可以消除重复的行。

并且,当你写一个冗长复杂的查询时,花一些时间格式化它,以便下一个必须理解它的草皮(可能是你几年)可以很容易地做到。

这会让你达到相同的目标:

SELECT cards.id   ,
       cards.name ,
       cards.created_at ,
       cards.updated_at
FROM       cards
INNER JOIN card_process     ON card_process.card_id = cards.id
INNER JOIN processes        ON processes.id = card_process.process_id
INNER JOIN category_process ON category_process.process_id = processes.id
INNER JOIN categories       ON categories.id =  category_process.category_id
INNER JOIN series           ON series.id = categories.serie_id
INNER JOIN serie_user       ON serie_user.serie_id = series.id
                           AND `cards`.`type` NOT IN ('', 'libraries')
                           AND NOT `cards`.`deleted`
                           AND NOT `categories`.`deleted`
                           AND NOT `series`.`deleted`
                           AND `cards`.`type` IN ('forms')
                           AND `series`.`id` IN (124,235,126,126,201,236,207,207,207,207,247,234,131,131,221,225,225,222)
UNION
SELECT cards.id   ,
       cards.name ,
       cards.created_at ,
       cards.updated_at
FROM cards
WHERE `cards`.`account_user_id`='9'
  AND NOT `cards`.`deleted`
  AND `cards`.`type` IN ('forms')
ORDER BY `updated_at` ASC
LIMIT 0, 25

如果MySql不允许限制完整选择,那么您可能需要附上select声明。

另外,有人可能会注意到您的加入条件几乎肯定不正确。在第一个选择中,表serie_user的连接条件有一堆测试:

AND `cards`.`type` NOT IN ('', 'libraries')
AND NOT `cards`.`deleted`
AND NOT `categories`.`deleted`
AND NOT `series`.`deleted`
AND `cards`.`type` IN ('forms')
AND `series`.`id` IN (124,235,126,126,201,236,207,207,207,207,247,234,131,131,221,225,225,222)

他们适用于加入serie_user的候选行。它们不适用于整个结果集。它们应该重构为where子句和相关表的连接标准,因此:

SELECT cards.id   ,
       cards.name ,
       cards.created_at ,
       cards.updated_at
FROM       cards
INNER JOIN card_process     ON card_process.card_id        = cards.id
INNER JOIN processes        ON processes.id                = card_process.process_id
INNER JOIN category_process ON category_process.process_id = processes.id
INNER JOIN categories       ON categories.id               =  category_process.category_id
                           AND NOT `categories`.`deleted`
INNER JOIN series           ON series.id                   = categories.serie_id
                           AND NOT `series`.`deleted`
                           AND     `series`.`id`           IN (124,235,126,126,201,236,207,207,207,207,247,234,131,131,221,225,225,222)
INNER JOIN serie_user       ON serie_user.serie_id         = series.id
WHERE `cards`.`type` NOT IN ('', 'libraries')
  AND NOT `cards`.`deleted`
  AND     `cards`.`type` IN ('forms')
UNION
SELECT cards.id   ,
       cards.name ,
       cards.created_at ,
       cards.updated_at
FROM cards
WHERE     `cards`.`account_user_id` = '9'
  AND NOT `cards`.`deleted`
  AND     `cards`.`type` IN ('forms')
ORDER BY `updated_at` ASC
LIMIT 0, 25

我要注意的最后一件事是你加入了一大堆未在结果集中使用的表格。您所做的只是从cards表中获取行的子集。这向我表明,如果你只是摆脱union和所有无关联,并且只是提出正确的问题,那么你可能会感觉更好。

这完全消除了重复的可能性。

一点点的重构让它归结为此(不能保证我已经100%正确,但你应该能够得到它的要点):

select c.id         ,
       c.name       ,
       c.created_at ,
       c.updated_at
from cards c
where   not c.deleted
  and       c.type            = 'forms'
  and (     c.account_user_id = '9'
        OR exists ( select *
                    from card_process     cp
                    join processes        p   on     p.id           = cp.process_id
                    join category_process cpx on     cpx.process_id = p.id
                    join categories       c   on     c.id           = cpx.category_id
                                             and not c.deleted
                    join series           s   on     s.id           = categories.serid_id
                                             and not s.deleted
                                             and     series.id IN ( 124 , 235 , 126 , ... )
                    join serie_user       su  on     su.serid_id     = s.id
                    where cp.card_id = c.card_id
                  )
      )
ORDER BY updated_at
LIMIT 0, 25

在复杂的查询中隐藏着一个简单的查询。

答案 1 :(得分:1)

是的,这就是UNION ALL的工作方式,它只是为您提供了所有查询的所有行。

如果您想删除重复项,请使用UNION,而不要使用ALL部分。