我有一个不寻常的SQL表(不是我的),其中包含以下字段(以及其他字段):last_name, primary_name, secondary_name
,表示已婚夫妇。假设姓氏是共享的(不是很现代,我知道),如果它不是一对,那么primary_name
或secondary_name
可能是NULL。 (该表也有几个重复。)
我想要做的是获取数据库中所有名称(“最后一个”)的列表,以通常的方式按字母顺序排列。现在我正在使用PHP和PDO对数据库进行两次传递:
$qstr = "SELECT DISTINCT primary_name, last_name
FROM members
WHERE primary_name IS NOT null
ORDER BY last_name, primary_name";
$sth = $dbh->prepare($qstr);
$sth->execute();
// output the results
$qstr = "SELECT DISTINCT secondary_name, last_name
FROM members
WHERE secondary_name IS NOT null
ORDER BY last_name, secondary_name";
$sth = $dbh->prepare($qstr);
$sth->execute();
// output the new results
但最终结果没有按字母顺序排列,因为第二遍再次开始。
如何一次性获取所有名称,完全按字母顺序排列?有没有办法在SQL中执行此操作,或者我是否需要构建两个数组并在之后使用PHP重新按字母顺序排列它们?
修改 数据库看起来像这样:
last_name primary_name secondary_name
----------------------------------------
Abrams Joe Susan
Miller Sam Abby
所需的输出将是这样的:
["Joe Abrams","Susan Abrams","Abby Miller","Sam Miller"]
相反,如果第一遍得到所有的丈夫,第二遍传递所有的妻子,我会得到这样的东西:
["Joe Abrams","Sam Miller","Susan Abrams","Abby Miller"]
答案 0 :(得分:7)
如果我理解正确,我认为你正在寻找这样的事情:
select distinct coalesce(primary_name, secondary_name) as pri_sec_name,
last_name
from members
where coalesce(primary_name, secondary_name) is not null
order by last_name,
coalesce(primary_name, secondary_name)
<强>更新强>
听起来在某些情况下,last_name有一行,其中primary_name和secondary_name都已填充。下面的查询应该为您提供所需的输出(抱歉,这次没有COALESCE):
select last_name, pri_sec_name
from (
select primary_name as pri_sec_name, last_name from members where primary_name is not null
union all
select secondary_name as pri_sec_name, last_name from members where secondary_name is not null
) a
order by last_name, pri_sec_name
答案 1 :(得分:2)
另一种方法是使用UNION ......
SELECT
*
FROM
(
SELECT primary_name AS pri_sec_name, last_name
FROM members
WHERE primary_name IS NOT null
UNION
SELECT secondary_name AS pri_sec_name, last_name
FROM members
WHERE secondary_name IS NOT null
)
AS data
ORDER BY
last_name, pri_sec_name
注意: UNION
(与UNION ALL
相对)将重复删除结果。
另一种方法是在映射表上进行连接。
SELECT
members.last_name,
CASE WHEN map.mode = 1 THEN members.primary_name ELSE members.secondary_name END AS pri_sec_name
FROM
members
INNER JOIN
(SELECT 1 as mode UNION ALL SELECT 2 as mode) AS map
ON (map.mode = 1 AND members.primary_name IS NOT NULL)
OR (map.mode = 2 AND members.secondary_name IS NOT NULL)
ORDER BY
1,
2
答案 2 :(得分:2)
我认为你需要:
SELECT primary_name AS name
, last_name
FROM members
WHERE primary_name IS NOT NULL
UNION
SELECT secondary_name
, last_name
FROM members
WHERE secondary_name IS NOT NULL
ORDER BY last_name, name
另一个重写是使用UNION ALL
:
SELECT COALESCE(primary_name, secondary_name) AS name
, last_name
FROM members
UNION ALL
SELECT secondary_name
, last_name
FROM members
WHERE primary_name IS NOT NULL
AND secondary_name IS NOT NULL
ORDER BY last_name, name
第二个版本可能会更快,但可能会显示重复的结果。如果有更多示例,您有这些行,一个Joe Jackson
与Susan
结婚,一个与Lea
结婚:
last_name primary_name secondary_name
----------------------------------------
Jackson Joe Susan
Jackson Joe Lea
第一个查询可以显示:
name last_name
-----------------
Joe Jackson
Lea Jackson
Susan Jackson
而第二个会有“重复”:
name last_name
-----------------
Joe Jackson
Joe Jackson
Lea Jackson
Susan Jackson
哪个更合适,取决于您的规格。