如何通过联合查找NOT NULL列?

时间:2018-08-26 05:19:27

标签: mysql

我有三个表:

1.table person

id, others
1, x
2, y
3, z
4, w

2表跟踪,外键(person_id)参考personid

id, person_id, ftime, details
1, 1, '2018-01-12', 'json_1'
2, 1, '2018-04-21', 'json_2'
3, 2, '2017-12-16', 'json_3'
4, 2, '2018-01-17', NULL
5, 3, '2018-06-02', 'json_5'
6, 4, '2018-01-19', NULL

3.table followup_track,外键(fid)参考followupid

id, fid, ftime, details
1, 1, '2018-01-27', 't_json_1'
2, 2, '2018-05-07', 't_json_2'
3, 5, '2018-06-17', 't_json_3'

现在,我想查找每个人的所有最后一次ftime,并且在跟踪和/或跟踪跟踪中,详细信息不为空。

我想要得到的结果是(这里的pid是人的身份证):

pid, ftime, details
1, '2018-05-07', 't_json_2'
2, '2017-12-16', 'json_3'
3, '2018-06-17', 't_json_3'

因为person.id = 4没有detalis!= NULL,所以结果不需要pid = 4。

由于person.id = 1的最后一次是'2018-05-07',因此需要该列。

我创建一个像这样的视图

CREATE VIEW view_full_flup AS
SELECT
  p.id AS pid, fp.ftime, fp.details
FROM
  ((followup_track fp
    LEFT JOIN followup ON (fp.fid = followup.id))
    LEFT JOIN person p ON (followup.person_id = p.id))
WHERE
  fp.details IS NOT NULL
UNION
SELECT
  f.person_id AS pid, f.ftime, f.details
FROM
  followup f
WHERE
  f.details IS NOT NULL

然后,我使用sql:

     SELECT *, MAX(`ftime`) FROM view_full_flup GROUP BY pid;

我的解决方案对吗?详细信息无法建立索引,而且速度很慢。请问如何正确执行此操作?

1 个答案:

答案 0 :(得分:0)

您不能选择star group by(嗯,您可能可以在MySQL中进行选择,具体取决于它的设置方式,但是要掌握sql技能的可移植性不是一个好习惯),必须指定一个列表您选择的列进行分组,或者将它们分组(在分组中放入列名称),或者对它们进行汇总(将列名称传递到聚合函数中)

感觉您的左联接逻辑倒退了-person是您知道记录所在的唯一表,因此它应该在联接的左侧。其他表可能是无记录的

这是我的查询,我会写得更像是:

select
  Pid,
  Max(case when ft.ftime > f.ftime then ft.ftime else f.ftime end) maxft
From
  Person p
  Left join (select * from followup where details is not null) f on f.person_id = p.id
  Left join (select * from follup_track where details is not null) ft on ft.fid = f.id
Group by pid

我们只连接了一组表,已经过滤掉了其中任一表的详细信息的记录,然后从任一表中获取了最大日期

请注意,如果您有记录(即使填写了详细信息),但date列为null,则此查询可以返回空日期。如果不希望有这些记录,则用HAVING过滤下摆或将整个内容包装在另一个select中,然后使用一个地方

Ps;从目前的情况来看,该查询似乎并不是特别有用,因为尽管您知道最近的日期,但是您没有任何其他数据。如果只是您想知道的全部(我无法从您的原始帖子中得知,因为描述和查询在他们所说的内容上是不同的),那么很好,但是如果您想要其他信息,也许使用mysql 8的新分析查询更适合:

Select * from
(
 select
  Pid,
  Row_number over(partition by pid order by (case when ft.ftime > f.ftime then ft.ftime else f.ftime end) desc) rown 
 From
  Person p
  Left join (select * from followup where details is not null) f on f.person_id = p.id
  Left join (select * from follup_track where details is not null) ft on ft.fid = f.id
) a where rown = 1