在一行中从 table 中选择 2 行的最佳方法是什么?
What is the best way for selecting 2 row from table in one row?
我有一个table喜欢关注
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
...
在这个table中,每个名字正好有两行(两个年级)。
我想查询结果如下
RESULT
PERSON_ID NAME GRADE1 GRADE_2
---------- ---------- ---------- ----------
1 NAME_1 10 20
2 NAME_2 30 40
最好的方法是什么。
我可以使用自连接,但我认为这不是正确的方法
为 SQL 服务器尝试此操作
; 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,并且所有的名字正好有两条记录,一年级是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
你可以按照对方的建议使用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 的行,因此您可以过滤掉重复项。
一旦话题发起人没有提到成绩的顺序,"there is exactly two rows (two grades)"我认为最简单的方法:
SELECT PERSON_ID,
MAX(NAME) as NAME,
MIN(GRADE) as GRADE1,
MAX(GRADE) as GRADE2
FROM TABLE_A
GROUP BY PERSON_ID
我在这个 link 中找到了 PostgreSQL 的最佳答案
https://www.postgresql.org/docs/9.2/static/tablefunc.html
在 PostgreSQL 中有 crosstab(text)
函数。
The crosstab function is used to produce "pivot" displays, wherein data is listed across the page rather than down. For example, we might have data like
row1 val11
row1 val12
row1 val13
...
row2 val21
row2 val22
row2 val23
...
which we wish to display like
row1 val11 val12 val13 ...
row2 val21 val22 val23 ...
...
The crosstab
function takes a text parameter that is a SQL query producing raw data formatted in the first way, and produces a table formatted in the second way.
The sql
parameter is a SQL statement that produces the source set of data.
This statement must return one row_name
column, one category
column, and one value
column. N
is an obsolete parameter, ignored if supplied (formerly this had to match the number of output value columns, but now that is determined by the calling query).
For example, the provided query might produce a set something like:
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
The crosstab
function is declared to return setof record
, so the actual names and types of the output columns must be defined in the FROM
clause of the calling SELECT
statement, for example:
SELECT * FROM crosstab('...') AS ct(row_name text, category_1 text, category_2 text);
This example produces a set something like:
<== value columns ==>
row_name category_1 category_2
----------+------------+------------
row1 val1 val2
row2 val5 val6
有关更多信息,请阅读 F.35.1.2. 部分 URL 进入答案顶部
我有一个table喜欢关注
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
...
在这个table中,每个名字正好有两行(两个年级)。 我想查询结果如下
RESULT
PERSON_ID NAME GRADE1 GRADE_2
---------- ---------- ---------- ----------
1 NAME_1 10 20
2 NAME_2 30 40
最好的方法是什么。 我可以使用自连接,但我认为这不是正确的方法
为 SQL 服务器尝试此操作
; 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,并且所有的名字正好有两条记录,一年级是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
你可以按照对方的建议使用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 的行,因此您可以过滤掉重复项。
一旦话题发起人没有提到成绩的顺序,"there is exactly two rows (two grades)"我认为最简单的方法:
SELECT PERSON_ID,
MAX(NAME) as NAME,
MIN(GRADE) as GRADE1,
MAX(GRADE) as GRADE2
FROM TABLE_A
GROUP BY PERSON_ID
我在这个 link 中找到了 PostgreSQL 的最佳答案
https://www.postgresql.org/docs/9.2/static/tablefunc.html
在 PostgreSQL 中有 crosstab(text)
函数。
The crosstab function is used to produce "pivot" displays, wherein data is listed across the page rather than down. For example, we might have data like
row1 val11
row1 val12
row1 val13
...
row2 val21
row2 val22
row2 val23
...
which we wish to display like
row1 val11 val12 val13 ...
row2 val21 val22 val23 ...
...
The
crosstab
function takes a text parameter that is a SQL query producing raw data formatted in the first way, and produces a table formatted in the second way. Thesql
parameter is a SQL statement that produces the source set of data. This statement must return onerow_name
column, onecategory
column, and onevalue
column.N
is an obsolete parameter, ignored if supplied (formerly this had to match the number of output value columns, but now that is determined by the calling query). For example, the provided query might produce a set something like:
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
The
crosstab
function is declared to returnsetof record
, so the actual names and types of the output columns must be defined in theFROM
clause of the callingSELECT
statement, for example:
SELECT * FROM crosstab('...') AS ct(row_name text, category_1 text, category_2 text);
This example produces a set something like:
<== value columns ==>
row_name category_1 category_2
----------+------------+------------
row1 val1 val2
row2 val5 val6
有关更多信息,请阅读 F.35.1.2. 部分 URL 进入答案顶部