6

我有一个不寻常的 SQL 表(不是我的),其中包含以下字段(以及其他字段): last_name, primary_name, secondary_name,表示已婚夫妇。假定姓氏是共享的(我知道这不是很现代),如果不是一对,那么primary_nameorsecondary_name可能是 NULL。(该表也有几个重复项。)

我想要做的是获取数据库中所有名称(“first last”)的列表,以通常的方式按字母顺序排列。现在我正在使用 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"]
4

3 回答 3

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
于 2012-04-24T14:26:48.927 回答
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
于 2012-04-24T14:45:32.213 回答
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 

哪个更合适,取决于您的规格。

于 2012-04-24T14:46:02.807 回答