【问题标题】:What is the best way for selecting 2 row from table in one row?从一行中的表中选择 2 行的最佳方法是什么?
【发布时间】:2017-02-04 19:11:30
【问题描述】:

我有一张如下表

TABLE_A
ID           PERSON_ID    NAME         GRADE
----------   ----------   ----------   ----------
1            1            NAME_1       10
2            1            NAME_1       20
3            2            NAME_2       30
4            2            NAME_2       40
...

在此表中,每个姓名正好有两行(两个等级)。 我想查询结果如下

RESULT
PERSON_ID    NAME         GRADE1       GRADE_2
----------   ----------   ----------   ----------
1            NAME_1       10            20
2            NAME_2       30            40

什么是最好的方法。 我可以使用自我加入,但我认为这不是正确的方法

【问题讨论】:

  • 如何计算 GRADE1 和 GRADE_2 ??
  • 哦。我认为激光名称将是 Name_2。
  • 您使用的是 MySQL 还是 Postgresql? (不要标记未涉及的产品。)
  • 您标记 MySQL 和 Postgresql,并接受 SQL Server 答案...

标签: mysql sql postgresql crosstab


【解决方案1】:

您可以按照其他人的建议使用 GROUP BY。

或者你可以加入。

select t1.person_id, t1.grade as grade1, t2.grade as grade2
from TABLE_A t1 join TABLE_A t2 on t1.person_id=t2.person_id and t1.id!=t2.id

此 JOIN 将所有具有同一个人的行连接起来,但不连接具有相同 id 的行,因此您可以过滤掉重复项。

【讨论】:

  • 有趣的方法 :) 我认为你应该使用 .. and t1.id<t2.id 而不是 != 所以第 1 级是第 1 级,第 2 级是第 2 级
  • 是的,你说得对,如果我们考虑到成绩是有序的,那会更好。
【解决方案2】:

如果您使用的是 MySQL,并且如果所有名称都恰好有两条记录,并且第一级是具有较低 id 的记录,而第二级是另一个,那么您可以使用这样的查询:

select
  person_id,
  name,
  group_concat(grade order by id) as grades
from
  table_a
group by
  person_id,
  name

如果您想将成绩分成两个新列,您可以使用 SUBSTRING_INDEX:

select
  person_id,
  name,
  substring_index(group_concat(grade order by id), ',', 1) as grade1,
  substring_index(group_concat(grade order by id), ',', -1) as grade2
from
  table_a
group by
  person_id,
  name

【讨论】:

    【解决方案3】:

    在 SQL SERVER 上试试这个

    ; WITH CTE AS(
    SELECT PERSON_ID, NAME, GRADE AS GRADE_1, 
    LEAD(GRADE) OVER(PARTITION BY NAME ORDER BY NAME) AS GRADE_2 
    FROM TABLE_A
    ) 
    SELECT * FROM CTE 
    WHERE GRADE_2 IS NOT NULL
    
    RESULT SET:
    
    PERSON_ID    NAME         GRADE_1       GRADE_2
    ----------   ----------   ----------   ----------
    1            NAME_1       10            20
    2            NAME_2       30            40
    

    【讨论】:

    • 这是 MySQL 还是 Postgresql 答案(或两者都有)?
    【解决方案4】:

    只要主题开始者没有提到成绩的顺序和“正好有两行(两个成绩)”,我认为最简单的方法:

    SELECT PERSON_ID, 
           MAX(NAME) as NAME, 
           MIN(GRADE) as GRADE1, 
           MAX(GRADE) as GRADE2
     FROM TABLE_A
     GROUP BY PERSON_ID
    

    【讨论】:

      【解决方案5】:

      我在此链接中找到了 PostgreSQL 的最佳答案 https://www.postgresql.org/docs/9.2/static/tablefunc.html 在 PostgreSQL 中有 crosstab(text) 函数。

      交叉表功能用于产生“透视”显示,其中数据列在整个页面而不是向下。例如,我们可能有像

      这样的数据
      row1    val11
      row1    val12
      row1    val13
      ...
      row2    val21
      row2    val22
      row2    val23
      ...
      

      我们希望显示的样子

      row1    val11   val12   val13   ...
      row2    val21   val22   val23   ...
      ...
      

      crosstab 函数接受一个文本参数,该参数是一个 SQL 查询,生成以第一种方式格式化的原始数据,并生成以第二种方式格式化的表。 sql 参数是生成源数据集的 SQL 语句。 此语句必须返回一个row_name 列、一个category 列和一个value 列。 N 是一个过时的参数,如果提供则忽略(以前它必须匹配输出值列的数量,但现在由调用查询确定)。 例如,提供的查询可能会产生一个类似的集合:

      row_name    cat    value
      ----------+-------+-------
        row1      cat1    val1
        row1      cat2    val2
        row1      cat3    val3
        row1      cat4    val4
        row2      cat1    val5
        row2      cat2    val6
        row2      cat3    val7
        row2      cat4    val8
      

      crosstab函数被声明为返回setof record,因此输出列的实际名称和类型必须在调用SELECT语句的FROM子句中定义,例如:

      SELECT * FROM crosstab('...') AS ct(row_name text, category_1 text, category_2 text);
      

      这个例子产生了一个类似的集合:

                 <== value  columns  ==>
       row_name   category_1   category_2
      ----------+------------+------------
        row1        val1         val2
        row2        val5         val6
      

      更多阅读部分F.35.1.2.在URL输入答案的顶部

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-23
        • 2023-03-17
        • 2010-09-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多