2011-12-22 43 views
7

我试图创建一个(sqlite)查询,它将执行GROUP BY,但不会将任何值与“unknown”组合在一起。例如,我有表:除了某些值以外的组

id | name | parent_id | school_id | 
1 | john | 1  | 1  | 
2 | john | 1  | 1  | 
3 | john | 1  | 1  | 
4 | nick | 2  | 2  | 
5 | nick | 2  | 2  | 
6 | nick | 3  | 3  | 
7 | bob  | 4  | 4  | 
8 | unknown | 5  | 5  | 
9 | unknown | 5  | 5  | 
10| unknown | 5  | 5  | 

与正确的查询“GROUP BY姓名,PARENT_ID,学校ID”我需要以下行返回:

id | name | parent_id | school_id | 
1 | john | 1  | 1  | 
3 | nick | 2  | 2  | 
4 | nick | 3  | 3  | 
5 | bob  | 4  | 4  | 
6 | unknown | 5  | 5  | 
7 | unknown | 5  | 5  | 
8 | unknown | 5  | 5  | 

任何帮助将不胜感激。谢谢!

+0

答案添加避免GROUP BY和解析表两次的成本。 – MatBailie 2011-12-22 23:59:04

回答

7

你不能轻易做到这一点有一个说法,但你可以UNION两个语句

  • GROUP所有unknown
  • 添加(UNION)的所有unknown的名单列表的结果

SQL Statement

SELECT MIN(id), name, parent_id, school_id 
FROM YourTable 
WHERE name <> 'unknown' 
GROUP BY 
     name, parent_id, school_id 
UNION ALL 
SELECT id, name, parent_id, school_id 
FROM YourTable 
WHERE name = 'unknown' 

请注意,我假设你已经张贴错unknown ID在你的结果

+0

绝对的辉煌! – Rahul 2011-12-22 23:43:22

+0

@Rahul - 印在墙上:) – 2011-12-22 23:47:38

+0

完美...谢谢! – Nick 2011-12-22 23:54:32

1
SELECT MIN(id), name, parent_id, school_id 
    FROM Table 
WHERE name <> 'unknown' 
GROUP BY name, parent_id, school_id 
UNION ALL 
SELECT id, name, parent_id, school_id 
    FROM Table 
WHERE name = 'unknown' 
+0

+1看起来有点相同。 – 2011-12-22 23:57:51

+0

是啊...但我喜欢你的答案......你没有解释尼克如何去关于查询:) – Akhil 2011-12-23 00:27:23

1
SELECT 
    MIN(id) AS id, 
    IF(tmpname=id,"unknown",tmpname) AS name, 
    parent_id, 
    school_id 
FROM (
    SELECT 
    id,parent_id,school_id 
    IF(name="unknown",id,name) AS tmpname 
    FROM <tablename> 
) AS baseview 
GROUP BY tmpname 
+0

+1有趣,但你应该在parent_id&school_id上分组,你不能对我的知识检查'tmpname = ID'在你的外部选择。 – 2011-12-23 00:02:06

+0

应该tmpid tmpid相同的方式 - 对不起 – 2011-12-23 00:03:36

+1

@Lievent - 同意,需要将这两个字段添加到GROUP BY,然后将第一个IF()块中的'id'更改为'MIN(id)'。我也明确地将整型转换为varchar(),以避免模糊,并尝试将varchar()转换为整数。 [在两个IF()块中。] – MatBailie 2011-12-23 00:14:17

2

作为一个单一的查询......

SELECT 
    MIN(id)   AS id, 
    name, 
    parent_id, 
    school_id 
FROM 
    yourTable 
GROUP BY 
    CASE WHEN name = 'unknown' THEN id ELSE 0 END, 
    name, 
    parent_id, 
    school_id 

或可能.. 。

GROUP BY 
    CASE WHEN name <> 'unknown' THEN name ELSE CAST(id AS VARCHAR(???)) END, 
    parent_id, 
    school_id 

-- Where VARCHAR(???) is the data type of the `name` field. 
-- Also assumes no value in `name` is the same as an id for an 'unknown' field 

两者都避免了UNION和两次解析表的开销,将其替换为稍微增加的复杂度GROUP BY

+0

+1 Afaik,这可以在SQL Server中工作,但SQLLite允许它吗? – 2011-12-23 00:06:50

+0

@Lieven - 我不知道tbh,它需要测试。除语法差异之外,这不会根据ANSI SQL破坏任何内容。我希望它可以工作,这不是一个复杂的查询... – MatBailie 2011-12-23 00:11:00

+0

不复杂,但不是立即想到的东西。虽然我不确定成本:UNION *可以*使用索引,而CASE是全表扫描。 OP将不得不比较执行计划来验证哪些功能性能最好。 – 2011-12-23 00:16:23

相关问题