获取SQL表另一列对应的行记录

Posted

技术标签:

【中文标题】获取SQL表另一列对应的行记录【英文标题】:Get corrosponding record Of Row in Another Column of SQL Table 【发布时间】:2019-08-05 13:20:15 【问题描述】:

我有一个 SQL 表,其中存储/保存了员工每天的记录我想以表格格式获得该结果

考虑如下所示的表格

 NAME     | DATEANDTIME         | ACTION 
----------|---------------------|-----------
JOHN      | 2019-07-07 10:00:00 |   INTIME
JOHN      | 2019-07-07 18:00:00 |   OUTTIME
WILLIAM   | 2019-07-07 10:02:00 |   INTIME
CATHERIN  | 2019-07-07 10:10:00 |   INTIME
JOHN      | 2019-07-07 13:00:00 |   LUNCH
CATHERIN  | 2019-07-07 18:30:00 |   OUTTIME
CATHERIN  | 2019-07-07 14:30:00 |   LUNCH
WILLIAM   | 2019-07-07 19:14:00 |   INTIME

我希望上面的表格以垂直格式显示,因为它应该按名称分组

我曾尝试使用数据透视查询,但它没有给我预期的输出

 select
    Dateandtime,
    [name],
    [action]
from
    (
        select Dateandtime,
        [name],
        [action]
    from
        table1) a pivot(max(action) for tagindex in (Dateandtime,
    [name],
    [action]))pvt


   INTIME            |      OUTTIME          | LUNCH               |  NAME
---------------------|-----------------------|---------------------|--------
#2019-07-07 10:00:00 | 2019-07-07 18:00:00   |        -------      | WILLIAM                                                    
#2019-07-07 10:10:00 | 2019-07-07 18:30:00   | 2019-07-07 14:30:00 |CATHERIN

【问题讨论】:

考虑处理应用代码中数据显示的问题。 顺便说一句,我认为标题与问题没有任何关系。 鉴于数据集是动态的,列应该以什么顺序出现? 【参考方案1】:

假设每个人的每种类型最多有一行,您可以使用条件聚合来做到这一点:

select name,
       max(case when action = 'INTIME' then dateandtime end) as intime,
       max(case when action = 'OUTTIME' then dateandtime end) as outtime,
       max(case when action = 'LUNCH' then dateandtime end) as lunch
from t
group by name;

如果给定名称有多个值,我建议您提出一个问题,详细说明如何处理这种情况。

【讨论】:

感谢您的即时回复,但动作可以是完全动态的,这只是我给出的 3 个场景,还有更多,比如请假、休息、会议、茶歇等等 如何动态处理同样,这是一天的场景,如果有说周的记录,这个查询将如何使用这个 使用pivot,你不能有动态的列数,除非你生成动态sql然后使用sp_executeSQL。但此时您的列数是可变的,因此您的下游报告/网页必须支持它。 @LALITACHAREKAR 。 . .然后你需要动态SQL。您可以查找正在使用的数据库的示例。 select name,dob,city max(case when action = 'INTIME' then dateandtime end) as intime, max(case when action = 'OUTTIME' then dateandtime end) as outtime, max(case when action = 'LUNCH' then dateandtime end) as lunch from t group by name;【参考方案2】:

考虑以下,它使用应用程序代码来处理数组的旋转/重新排列...

<?php

/*
DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,name VARCHAR(12) NOT NULL
,dt DATETIME NOT NULL
,action VARCHAR(12) NOT NULL
);

INSERT INTO my_table VALUES
(1,'John'     ,'2019-07-07 10:00:00','in'),
(2,'John'     ,'2019-07-07 18:00:00','out'),
(3,'William'  ,'2019-07-07 10:02:00','in'),
(4,'Catherine','2019-07-07 10:10:00','in'),
(5,'John'     ,'2019-07-07 13:00:00','lunch'),
(6,'Catherine','2019-07-07 18:30:00','out'),
(7,'Catherine','2019-07-07 14:30:00','lunch'),
(8,'William'  ,'2019-07-07 19:14:00','in');
*/

require('path/to/connnection/stateme.nts');

$query = "
SELECT id
     , name
     , dt
     , action
  FROM my_table
 ORDER
    BY name
     , action;
";

$result = mysqli_query($db,$query);

$array = array();

while($row = mysqli_fetch_assoc($result))
$array[] = $row;


foreach($array as $v)
$new_array[$v['name']][$v['action']] = $v['dt'];



print_r($new_array);

?>

输出:

Array
(
    [Catherine] => Array
        (
            [in] => 2019-07-07 10:10:00
            [lunch] => 2019-07-07 14:30:00
            [out] => 2019-07-07 18:30:00
        )

    [John] => Array
        (
            [in] => 2019-07-07 10:00:00
            [lunch] => 2019-07-07 13:00:00
            [out] => 2019-07-07 18:00:00
        )

    [William] => Array
        (
            [in] => 2019-07-07 19:14:00
        )

)

【讨论】:

select name,dob,city max(case when action = 'INTIME' then dateandtime end) as intime, max(case when action = 'OUTTIME' then dateandtime end) as outtime, max(case when action = 'LUNCH' then dateandtime end) as lunch from t group by name;我在此查询中还应用了其他列,但它不起作用 您在我的查询中看到任何聚合吗?不。在这种情况下,我无法理解您的评论的相关性。【参考方案3】:

我使用了一个适合我的 CTE,如下

WITH cte 
AS (SELECT Row_number() 
OVER( 
partition BY [name] 
ORDER BY [name]) AS rn, *FROM   table1)           
SELECT a.[dateandtime]  AS [IN], 
b.[dateandtime]  AS [OUT], 
a.[action]  AS [myaction], 
   c.[dateandtime]  AS [lunchTIME] 
FROM   (SELECT * 
FROM   cte a 
WHERE  rn = 1) a 
JOIN (SELECT * 
FROM   cte b 
WHERE  rn = 2) b 
ON a.[name] = b.[name] 
LEFT JOIN (SELECT * 
FROM   cte b 
WHERE  rn = 3) c 
ON a.[name] = c.[name]  

【讨论】:

以上是关于获取SQL表另一列对应的行记录的主要内容,如果未能解决你的问题,请参考以下文章

获取基于另一列的条件成立的每一行的最新记录(Hive SQL)

使用SQL修改一个表另一表也修改

SQL:根据另一列的值在列上保留一个具有最大值的行

根据唯一记录 postgres 将一列从一个 sql 表传输到另一列

SQL如何查询出某一列中不同值出现的次数?

SQL:两个数据库,都有包含公共值列的表。如何查找丢失的行