我知道mysql无法识别子查询中的外表,但遗憾的是我不知道如何解决这个问题。
首先是表结构,我有三个表(m到n):
表1: 跳舞
TAID | Name_Of_Dancer
1 | Alex Womitsch
2 | Julian Berger
表2: 舞者
TID | TAID
12 | 213
12 | 345
表3(引用表): dance2dancer
TID | AllDancerWhoDance
12 | 213---,345---,0---,0---,0---,0---,0---,0---,0---,0---
我想要实现什么(输出):
9 | 213---,345---,111---,459---,0---,0---,0---,0---,0---,0---
每个输出应该有舞蹈TID和所有在这个舞蹈中跳舞的舞者。但是当我们有不到10个舞者时,AllDancerWhoDance应该填满“0 ---”。当我们在这个舞蹈中有超过10个舞者时,查询应该将弦乐减少到最多10个舞者。
更多关于unterstand的例子: 与4位舞者一起跳舞应该填充6个零:
9 | 213---,345---,111---,459---,333---,444---,445---,222---,192---,490--- (NO more zeros or dancer TAIDs)
我们是否有超过10名舞者的舞蹈,查询应该减少到10:
select dancer.tid,
IF(count(dancer.taid) <= 10,
CONCAT_WS("",GROUP_CONCAT(dancer.taid,"&&&"), REPEAT(";0",10-count(dancer.taid)))
, (SELECT GROUP_CONCAT(a.taid,"&&&") from (SELECT ttt.taid from dance2dancer ttt inner join dance taenz on ttt.tid = taenz.tid where ttt.tid = dance.tid LIMIT 10) as a)
) AS "AllDancerWhoDance"
from dance inner join dance2dancer tt on dance.tid = tt.tid inner join dancer on tt.taid = dancer.taid group by dance.tid
以下是我的问题:
{{1}}
我认为它会起作用,但问题是子查询不会查看外表并且“where”子句不起作用:
其中ttt.tid = dance.tid
现在我的问题:
如何在mysql中实现这个sql查询?
谢谢
//更新
因为很多人要求提供前端代码以及为什么我需要这个查询:我们有一个22年的软件,需要这种格式的数据。它是由一家不再存在的公司编写的,我们没有该程序的任何源代码。我们已将数据库和网站更改为此新数据模型(m:n),但旧程序仍需要旧格式的数据。因此我需要这个奇怪的查询。
是的,我们正在制定一个新计划。
答案 0 :(得分:0)
为一个特定的舞蹈获得10个舞者:
select D.Name_Of_Dancer
from dancer DR, dance2dancer DD
where DD.taid = DR.taid
groupby DD.tid
Limit 10
您还可以添加Desc或ASC来对舞者列表的列表进行排序并提取前10个舞者。
但即使它不存在,也要在列表中获得最少10个舞者。它不可能通过mysql。我的意思是告诉我前端的代码你如何处理,我们可以做的是计算结果的数量。如果结果为4,我们可以简单地使用一个循环来创建6个其他条目以获得总共10个舞者。但我不建议从mysql端处理它们。这是一个不好的做法。
答案 1 :(得分:0)
您的错误原因是您无法从派生表(from (...) as a
)内部访问外部列。为此,您必须编写类似(...) as a where a.tid = dancer.tid
的内容,以便将where
放在派生表之外;但你显然必须以a
作为列重写tid
。
在你的情况下,修复你的代码会更复杂,所以我写了一个(更容易的)新代码:
select tid,
CONCAT_WS("",
(SELECT GROUP_CONCAT(d2d2.taid,"---")
from dance2dancer d2d2
where d2d2.tid = d2d.tid
group by d2d2.tid limit 10),
REPEAT(",0---",10-count(distinct d2d.taid))
) as `AllDancerWhoDance`
from dance2dancer d2d
group by d2d.tid
并发出警告:此类查询(在列中使用group_concat或concat)仅用于格式化要显示的数据的最后一步。如果您打算在其他查询中使用它,例如像select * from dancer where INSTR('213---,345---,111---', taid) > 0
之类的东西,请不要重写它。
更新而不使用limit 10
:
虽然limit 10
应该与group_concat一起使用(它适用于我),但是如果它不适合你,你当然可以连接所有内容,然后获取连接字符串的前10个条目然后。它实际上会简化查询,因为您不再需要子查询(只有第一个地方有limit
),但可能会生成一个大的临时字符串(在{{1}之前)如果你和很多舞者一起跳舞。
substring_index
或预先计算一个rownumber,然后只取每个tid的前10行:
select tid,
SUBSTRING_INDEX(CONCAT_WS("",
GROUP_CONCAT(d2d.taid,"---"),
REPEAT(",0---",10-count(distinct d2d.taid)),
','
), ',',10) as `AllDancerWhoDance`
from dance2dancer d2d
group by d2d.tid;