1

我知道 mysql 无法从子查询中识别外部表,但遗憾的是我不知道如何解决这个问题。

首先是表结构,我有三个表(m到n):

表1: 舞蹈

 TID | Name_Of_The_Dance   
 12  | Heute Tanz ich

表2: 舞者

TAID | Name_Of_Dancer
 1 | Alex Womitsch  
 2 | Julian Berger

表3(参考表): dance2dancer

TID | TAID   
 12 | 213   
 12 | 345 

我想实现什么(输出):

TID | AllDancerWhoDance  
12 |  213---,345---,0---,0---,0---,0---,0---,0---,0---,0--- 

每个输出都应该有舞蹈 TID 和在这个舞蹈中跳舞的所有舞者。但是当我们有少于 10 个舞者时,AllDancerWhoDance 应该填写“0---”。当我们在这个舞蹈中有超过 10 个舞者时,查询应该将字符串减少到最多 10 个舞者。

更多例子来理解: 一个有 4 个舞者的舞蹈应该用 6 个零填充:

9 | 213---,345---,111---,459---,0---,0---,0---,0---,0---,0---   

我们是否有超过 10 名舞者的舞蹈,查询应将其减少到 10:

9 | 213---,345---,111---,459---,333---,444---,445---,222---,192---,490--- (NO more zeros or dancer TAIDs)

这是我的查询:

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

我认为它会起作用,但问题是子查询没有查看外部表并且“where”子句不起作用:
where ttt.tid = dance.tid

现在我的问题是:
如何在 mysql 中实现这个 sql 查询?

谢谢

//UPDATE
因为很多人要求前端代码以及为什么我需要这个查询:我们有一个 22 年的软件,它需要这种格式的数据。它是由一家不再存在的公司编写的,我们没有该程序的任何源代码。我们已将数据库和网站更改为新的数据模型 (m:n),但旧程序仍需要旧格式的数据。因此我需要这个奇怪的查询。是的,我们也在开发一个新项目。

4

2 回答 2

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 端处理它们。这是一个不好的做法。

于 2016-05-05T10:32:52.903 回答
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可能会生成一个大的临时字符串(之前) substring_index.

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;

或预先计算一个行号,然后只取每个 tid 的前 10 行:

select d2d.tid, CONCAT_WS("",
  GROUP_CONCAT(d2d.taid,"---"),
  REPEAT(",0---",10-d2d.cnt)
  ) as `AllDancerWhoDance`
from 
(select tid, taid, 
      (select count(*) 
       from dance2dancer d2d4
       where d2d4.tid = d2d3.tid
       and d2d4.taid <= d2d3.taid
      ) as rownum,
      (select count(*) 
       from dance2dancer d2d4
       where d2d4.tid = d2d3.tid
      ) as cnt
      from dance2dancer d2d3
) as d2d
where d2d.rownum <= 10
group by d2d.tid;
于 2016-05-05T10:44:03.303 回答