My SQL Server 2008 report returns me multiple lines in a table. A simple select statement returns two columns, one is the record number the other is a sector. The sector column can contain any one of 6 different values.
EDIT: NULL values are allowed in the sector column.
I want this data to be in one line in my table.
Lets say record number 1 has Sector A, Sector C and Sector E
and Record 2 has Sector B and Sector C
And Record 3 has none.
I am after three lines of data. I also need it displayed two ways. One so that all sectors appear in the same cell separated by commas. The other is a separate Cell for each category
Record number | Sector
1 | A, C, E
2 | B, C
3 |
Or
Record Number | Sector A | Sector B | Sector C | Sector D | Sector E
1 | A | | C | | E
2 | | B | C | |
3 | | | | |
At the moment my report gives me 6 rows.
Record Number | Sector
1 | A
1 | C
1 | E
2 | B
2 | C
3 |
Is there a way of working around this problem?
I am using the query designer rather than writing the SQL statements.
In order to get the first result that you want with the comma-separated list of sector values, you will want to use FOR XML PATH and STUFF. The code will be:
select t1.recordnumber,
STUFF((SELECT ', ' + t2.sector
from yourtable t2
where t1.recordnumber = t2.recordnumber
FOR XML PATH (''))
, 1, 1, '') AS Sector
from yourtable t1
group by t1.recordnumber
See SQL Fiddle with Demo. The result is:
| RECORDNUMBER | SECTOR |
---------------------------
| 1 | A, C, E |
| 2 | B, C |
| 3 | (null) |
Then to get the result of the recordNumber in a single row, you can use the PIVOT function:
select *
from
(
select recordNumber, sector
from yourtable
) src
pivot
(
max(sector)
for sector in (A, B, C, D, E)
) piv;
See SQL Fiddle with Demo. The result of this query is:
| RECORDNUMBER | A | B | C | D | E |
-------------------------------------------------------------
| 1 | A | (null) | C | (null) | E |
| 2 | (null) | B | C | (null) | (null) |
| 3 | (null) | (null) | (null) | (null) | (null) |
Related
I have to perform a query where I can count the number of distinct codes per Id.
|Id | Code
------------
| 1 | C
| 1 | I
| 2 | I
| 2 | C
| 2 | D
| 2 | D
| 3 | C
| 3 | I
| 3 | D
| 4 | I
| 4 | C
| 4 | C
The output should be something like:
|Id | Count | #Code C | #Code I | #Code D
-------------------------------------------
| 1 | 2 | 1 | 1 | 0
| 2 | 3 | 1 | 0 | 2
| 3 | 3 | 1 | 1 | 1
| 4 | 2 | 2 | 1 | 0
Can you give me some advise on this?
This answers the original version of the question.
You are looking for count(distinct):
select id, count(distinct code)
from t
group by id;
If the codes are only to the provided ones, the following query can provide the desired result.
select
pvt.Id,
codes.total As [Count],
COALESCE(C, 0) AS [#Code C],
COALESCE(I, 0) AS [#Code I],
COALESCE(D, 0) AS [#Code D]
from
( select Id, Code, Count(code) cnt
from t
Group by Id, Code) s
PIVOT(MAX(cnt) FOR Code IN ([C], [I], [D])) pvt
join (select Id, count(distinct Code) total from t group by Id) codes on pvt.Id = codes.Id ;
Note: as I can see from sample input data, code 'I' is found in all of Ids. Its count is zero for Id = 3 in the expected output (in the question).
Here is the correct output:
DB Fiddle
Yesterday, after the help of a SO user #
Iterate over the rows of a second table to return resultset
I was able to make a combination of rows with a selfjoin.
After some modifications, to adapt to my implementation, I faced a new challenge that I'm stuck: how to make an aggregate sum of a third column?
My issue is better explained in the image below:
Based on the code
SELECT
b1.table_a_id,
b1.label_x,
b2.label_y
FROM table_a a
INNER JOIN table_b b1
ON b1.table_a_id = a.table_a_id
INNER JOIN table_b b2
ON b2.table_a_id = b1.table_a_id AND
b2.label_y > b1.label_x
ORDER BY
b1.table_a_id,
b1.label_x,
b2.label_y;
I was able to acquire the combinations.
What should be the next step to get the cumulative sum based on a third column?
I couldn't think of a solution without using a second service, such as python with pandas, using a cumsum function.
To generate the expected resultset, you would need to join the table with itself with an inequality condition on the order column. Then, you can do a window sum:
select
t1.table_a_id,
t1.label_x,
t2.label_y,
sum(t2.value) over(
partition by t1.table_a_id, t1.label_x
order by t1."order", t2."order"
) agg_value
from
table_b t1
inner join table_b t2
on t1.table_a_id = t2.table_a_id
and t2."order" >= t1."order"
order by t1."order", t2."order"
Note: order is a reserved word, so it needs to be quoted; if you actual database column has a different name, you can remove the double quotes.
Demo on DB Fiddle:
TABLE_A_ID | LABEL_X | LABEL_Y | AGG_VALUE
---------: | :------ | :------ | --------:
1 | A | B | 1
1 | A | C | 3
1 | A | D | 6
1 | A | E | 10
1 | A | F | 15
1 | B | C | 2
1 | B | D | 5
1 | B | E | 9
1 | B | F | 14
1 | C | D | 3
1 | C | E | 7
1 | C | F | 12
1 | D | E | 4
1 | D | F | 9
1 | E | F | 5
You seem to want a cumulative sum:
SELECT b1.table_a_id, b1.label_x, b2.label_y,
SUM(b1.value) OVER (PARTITION BY b1.table_a_id, b1.label_x
ORDER BY b2.order
) as AGG_VALUE
I know my subject is a little sparse, but for the life of me I cannot figure out how to do this. I could accomplish this in C# but I am getting confused by the SQL syntax. I searched and searched and I can't seem to find what I am looking for probably because I don't understand some of the SQL that I am looking at.
TABLE 1
-----------
| CustNo | Catalog1 | Catalog2 | Catalog3 | Catalog4 |
| 1 | A | B | C | NULL |
| 2 | B | C | NULL | D |
| 3 | A | C | E | F |
TABLE 2 (empty)
COLUMNS: CustNo|Catalog
So Basically for each record in Table 1, I want to insert the catalogs into table 2.
So the desired output would look like the following.
TABLE 2
CustNo|Catalog
| 1 | A
| 1 | B
| 1 | C
| 2 | B
| 2 | C
| 2 | D
| 3 | A
| 3 | C
| 3 | E
| 3 | F
Thank you all for any help!
Just unpivot. I like to do this using apply;
insert into table2 (CustNo, Catalog)
select t1.CustNo, v.Catalog
from table1 t1 cross apply
(values (t1.Catalog1), (t1.Catalog2), (t1.Catalog3), (t1.Catalog4)
) v(catalog)
where v.Catalog is not null;
I've got this DB. For starters, I didn't created this DB and I can't change the structure, so I have to deal with it.
+------+ +--------+ +--------+
| FORM | | FORM_A | | FORM_B |
+------+ +--------+ +--------+
| id | | form_id| | form_id|
| name | | name |
I'm not an Oracle user, I need to get all the FORM where I will get FORM_A datas as well as FORM_B, but I need to order it by name from both tables. "name" is the same kind of datas from FORM_A and FORM_B, too bad it's not in FORM.
Exemple :
FORM_A = [a, b, d, f]
FORM_B = [e, c, g]
FORM datas must be ordered as FORM_A(a), FORM_A(b), FORM_B(c), FORM_A(d), FORM_B(e)...
At first I think I'll have to order it manually with some loops, but I wonder if there is a way to order from multiples tables together, and not one after the other ?
you can
select *
from ( select id, null as name from form union all
select id, name from formA union all
select id, name from formB
) temp
order by temp.name
I am assuming the following table contents:
FORM FORM_A FORM_B
+----+--------+ +------+---------+ +------+---------+
| ID | NAME | | NAME | FORM_ID | | NAME | FORM_ID |
+----+--------+ |+-----+---------+ |+-----+---------+
| 1 | First | | a | 1 | | e | 3 |
| 2 | Second | | b | 2 | | c | 4 |
| 3 | Third | | d | 2 | | g | 5 |
| 4 | Fourth | | f | 3 | +------+---------+
| 5 | Fifth | +------+---------+
+----+--------+
You can use UNION to select from two tables, provided that the two tables have the same column structure:
SELECT FORM_A.form_id, FORM_A.name
FROM FORM_A
UNION ALL
SELECT FORM_B.form_id, FORM_B.name
FROM FORM_B
ORDER BY name;
FORM_ID NAME
---------- -----
1 a
2 b
4 c
2 d
3 e
3 f
5 g
By joining the FORM_ID with the FORM table, you then get the corresponding rows from FORM:
SELECT ab.Name AS AB, f.Name AS DATA
FROM (SELECT FORM_A.form_id, FORM_A.name
FROM FORM_A
UNION ALL
SELECT FORM_B.form_id , FORM_B.name
FROM FORM_B
ORDER BY name) ab
JOIN FORM f ON f.id=ab.FORM_ID;
AB DATA
----- ----------
a First
b Second
c Fourth
d Second
e Third
f Third
g Fifth
i want to start by saying that i know there are a couple of questions regarding similar problems but they either dont answer my question fully or seem to be incompatible with SQLite.
I want to query all rows with value -1 and the first rows with values other than -1.
And by "first rows" i mean the group of rows that are first with a certain value. the first row is the row that is first stumbled upon depending on the SORT BY clause
An example of the data and outcome:
Data:
a b -1
c d 1
e f 2
g h 2
i j 2
k l -1
Result:
a b -1
c d 1
e f 2
k l -1
And as said above, i am using a SQLite database
Do this as two separate queries, one of them containing an inline view; UNION the two
select blah, blah from T where ...
UNION
select * from
(
select blah, blah from T where something else order by somecolumn limit 1
)
With simple example:
> select * from ex1;
+------+----------+
| id | name |
+------+----------+
| 1 | Pirate |
| 2 | Monkey |
| 3 | Ninja |
| 4 | Spagheti |
| 5 | kumar |
| 6 | siva |
+------+----------+
> select * from ex1 union select "1", "sing" order by case name when 'sing' then 1 else 2 end, name;
+------+----------+
| id | name |
+------+----------+
| 1 | sing |
| 5 | kumar |
| 2 | Monkey |
| 3 | Ninja |
| 1 | Pirate |
| 6 | siva |
| 4 | Spagheti |
+------+----------+