sql server transpose rows to column value - sql

I have a table that looks like this:
Project | State
----------------
1 | A
2 | A
2 | F
3 | A
3 | F
3 | P
4 | S
5 | C
What i would like to to is get a table like this :
Project | State
----------------
1 | A
2 | AF
3 | AFP
4 | S
5 | C
Is it possible to do this ?

SELECT Project,
(SELECT State + ''
FROM table t
WHERE t.project = m.project
FOR XML PATH(''))
FROM table m
GROUP BY Project

Related

How to concatenate results of multiple rows

I currently have a view in SQL Server, something like this:
Table1:
Id
Desc
Mex
Table2:
Id
IdTab1
Desc
The view select everything from Table1 left joined on Table2 on Id - IdTab1
Now I have a table 3 joined with Table2 that has like these fields:
Table3:
Id
IdTab2
Code (VarChar(3))
I would like to have in the select of the view a new field Code that contains every code in table 3 concatenated with the char ' ' without changing the record displayed from the old query (so like doing a group by concat) every Code that matches the join.
I saw some other posts but neither of them used this kind of approach.
For example using this:
declare #result varchar(500)
set #result = ''
select #result = #result + ModuleValue + ', '
from TableX where ModuleId = #ModuleId
But I have faced two problems.
I could not use declare in the view (probably because of wrong syntax), and also I have to do this group by and I can't figure out how.
Example result basic view
ID | IDTAB2 | DESC1 | DESC2 | MEX
1 | 2 | aa | bb | 4
2 | 1 | ab | cc | 2
2 | 2 | bb | bc | 2
Example result joined Table3
ID | IDTAB2 | DESC1 | DESC2 | MEX | CODE
1 | 2 | aa | bb | 4 | CS
1 | 2 | aa | bb | 4 | NN
2 | 1 | ab | cc | 2 | AF
2 | 2 | bb | bc | 2 | DC
2 | 2 | bb | bc | 2 | KK
2 | 2 | bb | bc | 2 | JD
Example result needed
ID | IDTAB2 | DESC1 | DESC2 | MEX | CODENEW
1 | 2 | aa | bb | 4 | CS NN
2 | 1 | ab | cc | 2 | AF
2 | 2 | bb | bc | 2 | DC KK JD
Considering your output from "Example result joined Table3", you can try this below option based on your SQL server version-
For MSSQL-2016 and earlier- Demo
SELECT DISTINCT A.ID,A.IDTAB2,A.DESC1,A.DESC2,A.MEX,
SUBSTRING(
(
SELECT ' '+ B.CODE AS [text()]
FROM your_table B
WHERE B.ID = A.ID
AND B.IDTAB2 = A.IDTAB2
AND B.DESC1 = A.DESC1
AND B.DESC2 = A.DESC2
AND B.MEX = A.MEX
ORDER BY B.ID,B.IDTAB2,B.DESC1,B.DESC2,B.MEX
FOR XML PATH ('')
), 2, 1000) [C_Name]
FROM your_table A
For MSSQL-2017 or newer- Demo
SELECT ID,IDTAB2,DESC1,DESC2,MEX,
STRING_AGG ( CODE, ' ' )
FROM your_table
GROUP BY ID,IDTAB2,DESC1,DESC2,MEX

Count the number of appearances of char given a ID

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

Need sql help: For each record in table A (has more columns than table B), insert into Table B

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;

select records where condition is true in one record

I need to select cid, project, and owner from rows in the table below where one or more rows for a cid/project combination has an owner of 1.
cid | project | phase | task | owner
-----------------------------------
1 | 1 | 1 | 1 | 1
1 | 1 | 1 | 2 | 2
1 | 1 | 1 | 3 | 2
2 | 1 | 1 | 1 | 1
2 | 1 | 1 | 2 | 1
3 | 1 | 1 | 3 | 2
My output table should look like the this:
cid | project | phase | task | owner
-----------------------------------
1 | 1 | 1 | 1 | 1
1 | 1 | 1 | 2 | 2
1 | 1 | 1 | 3 | 2
2 | 1 | 1 | 1 | 1
2 | 1 | 1 | 2 | 1
The below query is what I came up with. It does seem to test okay, but my confidence is low. Is the query an effective way to solve the problem?
select task1.cid, task1.project, task1.owner
from
(select cid, project, owner from table) task1
right join
(select distinct cid, project, owner from table where owner = 1) task2
on task1.cid = task2.cid and task1.project = task2.project
(I did not remove the phase and task columns from the sample output so that it would be easier to compare.)
You can simply use a IN clause
select cid, project, owner
from table
where cid in (select distinct id from table where owner = 1)
or a inner join with a subquery
select a.cid, a.project, a.owner
from table a
INNER JOIN ( select distinct cid , project
from table where owner = 1
) t on t.cid = a.cid and t.project = a.project

Exclude a group when one row match in another table

I have two tables :
the first one called "card" with one column "id".
| id |
| 1 |
| 2 |
| 3 |
| .. |
The second table is named "waste" with two columns "card_id" and "waste_type".
| card_id | waste_type |
| 1 | 1 |
| 1 | 3 |
| 2 | 2 |
| 2 | 1 |
And i want to select only the card where there is no waste_type = 2
The query should look like this :
SELECT c.id FROM card c
JOIN waste w
ON c.id = w.card_id
WHERE waste_type <> 2
I want this result :
id
1
But i get :
id
1
2
How can i do that ? Thank you so much in advance !
You should use a not exists clause for that.
select c.id
from card c
where not exists (select null from waste w
where w.card_id = c.id
and w.waste_type = 2)
With your query, I would guess you rather retrieve
1
1
2