3

UPDATE:

my orgional attempt to use FULL OUTER JOIN did not work correctly. I have updated the question to reflex the true issue. Sorry for presenting a classic XY PROBLEM.


I'm trying to retrieve a dataset from multiple tables all in one query thats is grouped by year, month of the data.

The final result should look like this:

| Year | Month | Col1 | Col2 | Col3 |
|------+-------+------+------+------|
| 2012 |   11  |  231 |   -  |  -   |
| 2012 |   12  |  534 |  12  |  13  |
| 2013 |   1   |   -  |  22  |  14  |

Coming from data that looks like this:

Table 1:

| Year | Month | Data |
|------+-------+------|
| 2012 |   11  |  231 |
| 2012 |   12  |  534 |

Table 2:

| Year | Month | Data |
|------+-------+------|
| 2012 |   12  |  12  |
| 2013 |   1   |  22  |

Table 3:

| Year | Month | Data |
|------+-------+------|
| 2012 |   12  |  13  |
| 2013 |   1   |  14  |

I tried using FULL OUTER JOIN but this doesn't quite work because in my SELECT clause because no matter which table I select 'Year' and 'Month' from there are null values.

SELECT 
 Collase(t1.year,t2.year,t3.year)
,Collese(t1.month,t2.month,t3.month)
,t1.data as col1
,t2.data as col2
,t3.data as col3
From t1
FULL OUTER JOIN t2
on t1.year = t2.year and t1.month = t2.month
FULL OUTER JOIN t3
on t1.year = t3.year and t1.month = t3.month

Result is something like this (is too confusing to repeat exactly what i would get using this demo data):

| Year | Month | Col1 | Col2 | Col3 |
|------+-------+------+------+------|
| 2012 |   11  |  231 |   -  |  -   |
| 2012 |   12  |  534 |  12  |  13  |
| 2013 |   1   |   -  |  22  |      |
|  -   |   1   |   -  |  -   |  14  |
4

6 に答える 6

2

If your data allows it (not 100 columns), this is usually a clean way of doing it:

select year, month, sum(col1) as col1, sum(col2) as col2, sum(col3) as col3
from (
    SELECT t1.year, t1.month, t1.data as col1, 0 as col2, 0 as col3
    From t1
    union all 
    SELECT t2.year, t2.month, 0 as col1, t2.data as col2, 0 as col3
    From t2
    union all 
    SELECT t3.year, t3.month, 0 as col1, 0 as col2, t3.data as col3
    From t3
) as data
group by year, month
于 2012-12-04T20:45:15.237 に答える
1

Perhaps you are looking for the COALESCE keyword? It takes a list of columns and returns the first one that is NOT NULL, or NULL if all arguments are null. In your example, you would do something like this.

SELECT COALESCE(t1.data, t2.data)

You would still need to join tables in this case. It would just cut down on the case statements.

于 2012-12-04T20:47:42.940 に答える
1

You could derive the complete list of years and months from all the tables, than join every table to that list (using a left join):

SELECT 
  f.Year,
  f.Month,
  t1.data AS col1,
  t2.data AS col2,
  t3.data AS col3
FROM (
  SELECT Year, Month FROM t1
  UNION
  SELECT Year, Month FROM t2
  UNION
  SELECT Year, Month FROM t3
) f
LEFT JOIN t1 ON f.year = t1.year and f.month = t1.month
LEFT JOIN t2 ON f.year = t2.year and f.month = t2.month
LEFT JOIN t3 ON f.year = t3.year and f.month = t3.month
;

You can see a live demonstration of this query at SQL Fiddle.

于 2012-12-04T22:36:29.720 に答える
1

If you are using SQL Server 2005 or later version, you could also try this PIVOT solution:

SELECT 
  Year,
  Month,
  Col1,
  Col2,
  Col3
FROM (
  SELECT Year, Month, 'Col1' AS Col, Data FROM t1
  UNION ALL
  SELECT Year, Month, 'Col2' AS Col, Data FROM t2
  UNION ALL
  SELECT Year, Month, 'Col3' AS Col, Data FROM t3
) f
PIVOT (
  SUM(Data) FOR Col IN (Col1, Col2, Col3)
) p
;

This query can be tested and played with at SQL Fiddle.

于 2012-12-04T22:43:10.980 に答える
0

if you are looking for the non-null values from either tabloe then you will have to add t1.dat IS NOT NULL as well. I hope that I understand your question.

CREATE VIEW joined_SALES
AS SELECT t1.year, t1.month, t1.data , t2.data 
FROM table1 t1, table2 t2
WHERE
    t1.year = t2.year 
    and    t1.month = t2.month
    and    t1.dat IS NOT NULL
GROUP BY t1.year, t1.month;
于 2012-12-04T20:15:34.587 に答える
0

This might be a better way, especially if you are going to do something with the data before returning it. Basically you are translating the table the data came from into a typeId.

declare @temp table 
([year] int,
[month] int,
typeId int,
data decimal)


insert into @temp
SELECT t1.year, t1.month, 1,  sum(t1.data)
From t1
group by t1.year, t1.month

insert into @temp
SELECT t2.year, t2.month, 2,  sum(t2.data)
From t2
group by t1.year, t1.month


insert into @temp
SELECT t3.year, t3.month, 3,  sum(t3.data)
group by t1.year, t1.month


select t.year, t.month, 
sum(case when t.typeId = 1 then t.data end) as col1, 
sum(case when t.typeId = 2 then t.data end) as col2, 
sum(case when t.typeId = 3 then t.data end) as col3 
from @temp t
group by t.year, t.month
于 2012-12-04T21:24:02.513 に答える