'紧凑' SELECT结果在mySQL中

时间:2015-09-21 05:28:33

标签: mysql sql

无论如何都有' compact' SQL查询的结果?

结果如下:

Project
  .select("projects.*, max(project_reports.created_at) as latest_report")
  .joins(:project_reports)
  .order("latest_report desc")
  .group("projects.id")
  .preload(:project_reports)
  .map { |p| "#{p.name}: #{p.latest_report_number}" }

但我希望它看起来像这样:

+----+-----------+----------+-----------+-------------+--------+
| ID | Firstname | Lastname |   Hobby   |     Job     |  Age   |
+----+-----------+----------+-----------+-------------+--------+
| 1  | John      | Doe      | (null)    | (null)      | 30     |
| 1  | John      | Doe      | Chess     | (null)      | (null) |
| 2  | Adam      | Jackson  | (null)    | Accountant  | (null) |
| 2  | Adam      | Jackson  | (null)    | (null)      | 55     |
| 3  | Michael   | Smith    | Knitting  | (null)      | (null) |
| 3  | Michael   | Smith    | (null)    | Banker      | (null) |
+----+-----------+----------+-----------+-------------+--------+

我尝试使用+----+-----------+----------+-----------+-------------+--------+ | ID | Firstname | Lastname | Hobby | Job | Age | +----+-----------+----------+-----------+-------------+--------+ | 1 | John | Doe | Chess | (null) | 30 | | 2 | Adam | Jackson | (null) | Accountant | 55 | | 3 | Michael | Smith | Knitting | Banker | (null) | +----+-----------+----------+-----------+-------------+--------+ ,但它只接受数据库中每个人的第一个自定义字段。

我在这里设置了一个SQL小提琴:http://sqlfiddle.com/#!9/39563/2

设置有点奇怪,但由于我正在处理的数据库,我需要保留该结构。

3 个答案:

答案 0 :(得分:2)

您可以使用max聚合函数group by来平整结果,如下所示:

select 
  p.id as "User ID", 
  p.firstname Firstname, 
  p.lastname as Lastname,
  max(case when cf.fieldname = 'Hobby' then cfv.value end) as "Hobby",
  max(case when cf.fieldname = 'Job'   then cfv.value end) as "Job",
  max(case when cf.fieldname = 'Age'   then cfv.value end) as "Age"
from CustomFields cf 
join CustomFieldValues cfv on cfv.fieldid = cf.id
join People p on cfv.relid = p.id
where cf.fieldname in ('Hobby', 'Job', 'Age')
group by p.id, p.firstname, p.lastname 
order by p.id;

此外,字符串文字应包含在单引号中,您可以使用别名来减少查询文本并使其更具可读性。

Your Fiddle, updated

答案 1 :(得分:0)

使用组中的group_concat函数作为字符串值的函数和数字字段的最大函数。

SELECT id, FirstName, LastName, 
   GROUP_CONCAT(CASE WHEN Hobby IS NOT NULL THEN Hobby END) AS Hobby,
   GROUP_CONCAT(CASE WHEN Job IS NOT NULL THEN Job END AS Job, 
   MAX(Age) AS Age 
FROM TableGROUP BY id

答案 2 :(得分:0)

您应该将MAX计算移动到派生表中,以便在加入之前应用聚合。这将提高性能:

select p.id as "User ID", p.firstname Firstname, p.lastname as Lastname,
cf.Hobby,
cf.Job,
cf.Age
from 
 (
   select cfv.relid,
      max(case when cf.fieldname = "Hobby" then cfv.value end) as "Hobby",
      max(case when cf.fieldname = "Job" then cfv.value end) as "Job",
      max(case when cf.fieldname = "Age" then cfv.value end) as "Age"
   from CustomFields as cf inner join CustomFieldValues as cfv
     on cfv.fieldid = cf.id
   where cf.fieldname = "Hobby"
      or cf.fieldname = "Job"
      or cf.fieldname = "Age"
   group by cfv.relid
/* -- apply additional conditions here, e.g. "all three fields must be set"
   having Hobby is not null 
      and Job is not null
      and age is not null 
*/
 ) as cf
inner join People as p
   on cf.relid = p.id
order by p.id

fiddle