计算记录时出现SQL UNION问题

时间:2010-09-30 19:50:52

标签: sql union

我有以下数据库架构(名称已更改以保护无辜者)

Code Table

| code_id | code_desc |
|---------|-----------|
| 1       | good      |
|---------|-----------|
| 2       | bad       |
|---------|-----------|
| 3       | ugly      |
|---------|-----------|

Foo Table                               AssignedFoo Table

| foo_id | foo_desc | foo_dt    |       | assn_id | foo_id | code_id |
|--------|----------|-----------|       |---------|--------|---------|
| 101    | red      | 1/1/2000  |       | 301     | 101    | 1       |
|--------|----------|-----------|       |---------|--------|---------|
| 102    | green    | 6/1/2000  |       | 302     | 102    | 2       |
|--------|----------|-----------|       |---------|--------|---------|
| 102    | blue     | 12/1/2000 |
|--------|----------|-----------|

Bar Table                               AssignedBar Table

| bar_id | bar_desc | bar_dt    |       | assn_id | foo_id | code_id |
|--------|----------|-----------|       |---------|--------|---------|
| 201    | gold     | 12/1/2000 |       | 401     | 201    | 1       |
|--------|----------|-----------|       |---------|--------|---------|
| 202    | silver   | 1/1/2001  |       | 402     | 202    | 3       |
|--------|----------|-----------|       |---------|--------|---------|
| 202    | bronze   | 6/1/2001  |
|--------|----------|-----------|

我想计算映射到Code表的记录数,无论它们是foos还是bar。虽然我有以下查询可行。

SELECT
    COUNT(c.code_id) AS coded,
    c.code_desc
FROM 
    code c
    INNER JOIN assignedfoo af ON af.code_id = c.code_id
    INNER JOIN foo f ON f.foo_id = af.foo_id
WHERE
    f.foo_dt >= [start date] AND 
    f.foo_dt <= [end date]
GROUP BY 
    c.code_desc

UNION ALL   

SELECT
    COUNT(c.code_id) AS coded,
    c.code_desc
FROM 
    code c
    INNER JOIN assignedbar ab ON ab.code_id = c.code_id
    INNER JOIN bar b ON b.bar_id = ab.bar_id
WHERE
    b.bar_dt >= [start date] AND 
    b.bar_dt <= [end date]
GROUP BY 
    c.code_desc 

不幸的是,我得到以下结果集

| coded | code_desc |
|-------|-----------|
| 1     | good      |
|-------|-----------|
| 1     | good      |
|-------|-----------|
| 1     | bad       |
|-------|-----------|
| 1     | ugly      |
|-------|-----------|

我想要的是这个

| coded | code_desc |
|-------|-----------|
| 2     | good      |
|-------|-----------|
| 1     | bad       |
|-------|-----------|
| 1     | ugly      |
|-------|-----------|

有关如何解决此问题的任何建议?

非常感谢任何帮助。

谢谢!

4 个答案:

答案 0 :(得分:1)

我认为你只需要按照以下方式将小组移动到你的工会之外:

select count(a.code_id) as Coded, a.code_desc
from (
SELECT
    c.code_id,
    c.code_desc
FROM 
    code c
    INNER JOIN assignedfoo af ON af.code_id = c.code_id
    INNER JOIN foo f ON f.foo_id = af.foo_id
WHERE
    f.foo_dt >= [start date] AND 
    f.foo_dt <= [end date]

UNION ALL   

SELECT
    c.code_id,
    c.code_desc
FROM 
    code c
    INNER JOIN assignedbar ab ON ab.code_id = c.code_id
    INNER JOIN bar b ON b.bar_id = ab.bar_id
WHERE
    b.bar_dt >= [start date] AND 
    b.bar_dt <= [end date]
) a
group by a.code_desc

答案 1 :(得分:0)

使用此

Select COUNT(UnionTable.coded),UnionTable,code_description from 

(SELECT
    COUNT(c.code_id) AS coded,
    c.code_desc code_description
FROM 
    code c
    INNER JOIN assignedfoo af ON af.code_id = c.code_id
    INNER JOIN foo f ON f.foo_id = af.foo_id
WHERE
    f.foo_dt >= [start date] AND 
    f.foo_dt <= [end date]
GROUP BY 
    c.code_desc

UNION ALL   

SELECT
    COUNT(c.code_id) AS coded,
    c.code_desc code_description
FROM 
    code c
    INNER JOIN assignedbar ab ON ab.code_id = c.code_id
    INNER JOIN bar b ON b.bar_id = ab.bar_id
WHERE
    b.bar_dt >= [start date] AND 
    b.bar_dt <= [end date]
GROUP BY 
    c.code_desc ) UnionTable

   group by UnionTable.code_description 

答案 2 :(得分:0)

在计算之前建立联盟:

SELECT
    COUNT(*) AS coded,
    x.code_desc
FROM (

  SELECT
    c.code_desc, f.foo_dt
  FROM 
    code c
    INNER JOIN assignedfoo af ON af.code_id = c.code_id
    INNER JOIN foo f ON f.foo_id = af.foo_id

  UNION ALL   

  SELECT
    c.code_desc, f.foo_dt
  FROM 
    code c
    INNER JOIN assignedbar ab ON ab.code_id = c.code_id
    INNER JOIN bar b ON b.bar_id = ab.bar_id

) x
WHERE
  x.foo_dt >= [start date] AND 
  x.foo_dt <= [end date]
GROUP BY 
  x.code_desc

答案 3 :(得分:0)

当您在计数之外进行联合时,您将“追加”行添加到第一组。如果未指定“all”,它将尝试返回DISTINCT集,因此包含“GOOD 1”的两行将导致单行“GOOD 1”。如果您执行UNION ALL,它只会附加但不会添加。

你需要做的是总结工会:

SELECT c.code_desc, s.COUNT(NUM)
FROM
Code c JOIN
(
    SELECT code_id, COUNT(*) AS NUM
      FROM AssignedFoo af
      JOIN Foo f on af.foo_id = f.foo_id
      WHERE f.foo_dt >= [start date]
        AND f.foo_dt <= [end date]
    GROUP BY CODE_ID
    UNION ALL
    SELECT CODE_ID, COUNT(*) AS NUM
      FROM AssignedBar ab
      JOIN Bar b on ab.bar_id = b.bar_id
      WHERE b.bar_dt >= [start date]
        AND b.bar_dt <= [end date]
    GROUP BY code_id
) s ON c.code_id = s.code_id
GROUP BY c.code_id