这个问题已经有了最合适的回答,请快速访问这里。
此查询返回多个结果。 在底部,您可以看到每个ID号都有两个。 如何区分仍记录有25个唯一值的记录?
选择*
从(
选择
DISTINCT cards.id、cards.name、cards.created_at、cards.updated_at
来自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
和卡`.` type ` not in (',' libraries ' ) )
和not ` cards `.` deleted `
和not ` categories `.` deleted `
和not ` series `.` deleted `
AND `cards`.`type` IN ('forms ' )
and`series`.`id`in(124、235、126、126、201、236、207、207、247、234、131、131、221、225和225
全部合并
选择
DISTINCT cards.id、cards.name、cards.created_at、cards.updated_at
来自cards
where ` cards `.` account _ user _ id `='9'
和not ` cards `.` deleted `
AND `cards`.`type` IN ('forms ' )
) AS qry
ORDER BY `updated_at` ASC
limit 0,25
用UNION代替UNION ALL。
我对模式和数据的形状一无所知,所以可以通过简化查询来获得所需的内容。 假设它基本符合标准的SQL方言
不需要附带的选择。 “全选”(unionedselectexpressions )接受应用于所有选择的order by。
UNION中的单个select语句不需要distinct关键字。 UNION本身消除了重复行。
创建长而复杂的查询时,请花时间格式化,以便下一个必须了解的SOD (可能几年后是你)可以轻松完成这项工作。
这是以下情况:
SELECT cards.id,
cards.name,
cards.created_at,
cards.updated_at
来自cards
innerjoincard _ processo ncard _ process.card _ id=cards.id
innerjoinprocessesonprocesses.id=card _ process.process _ id
innerjoincategory _ processoncategory _ process.process _ id=processes.id
innerjoincategoriesoncategories.id=category _ process.category _ id
innerjoinseriesonseries.id=categories.serie _ id
innerjoinserie _ useronserie _ user.serie _ id=series.id
和卡`.` type ` not in (',' libraries ' ) )
和not ` cards `.` deleted `
和not ` categories `.` deleted `
AND N
OT `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
。
通常有一个简单的查询隐藏在一个复杂的查询中。
有趣的格式样式。我个人觉得很疯狂,但我明白你为什么要哀求我。
@lydxg:SQL语法已经够糟糕了。当查询变得复杂时,您需要能够摸索它。O.P.嵌套连接布局是一种代码味道,它指示过程性思维(嵌套循环),而不是在集合、关系代数和谓词演算方面感谢。此外,许多认知研究表明,规则的表格布局可以增强理解。人们摸索桌子。
@简单的秋天,我同意。操作的代码是一团糟的,我会自己避免所有的T-SQL。但你的格式很有意思,但却把我逼到了墙边。但每个人都有。
哇,太棒了!通常我对所有数据库交互都使用ORM,您有SQL的样式指南吗?上面的查询是来自其他人的风格,所以我刚刚了解。
来自维基百科Transact-SQL (T-SQL) is Microsoft's and Sybase's proprietary…哦,该死的……
我所写的内容中没有特定于T-SQL的内容。除了limit子句之外,所有普通的、标准的SQL都应该适用于任何合理的、符合标准的SQL实现。
是的,这就是UNION ALL的工作原理,它只提供两个查询的所有行。
如果要删除重复项,请使用UNION,不使用ALL部分。
你也可以用UNION DISTINCT把它表达出来。
UNION ALL到UNION固定,再过10分钟就不能接受了。
@Barmar我看不出我的结果集在有或没有UNION DISTINCT的情况下有什么不同。
UNION和UNION DISTINCT是相同的,它们都删除了重复项。UNION ALL叶重复。