Group Rows Together in Join [duplicate] - sql

This question already has answers here:
How do I create a comma-separated list using a SQL query?
(11 answers)
Closed 18 days ago.
I have a table that contains a bunch of keys with different IDs. Some keys have more than 1 ID.
ID Table:
key id
a 1
a 11
a 12
b 2
c 3
c 33
2nd table:
key count location
a 17 123 Test Rd
b 10 12 Smith St
c 18 999 Fire Rd
Desired result:
key count location id
a 17 123 Test Rd 1, 11, 12
b 10 12 Smith St 2
c 18 999 Fire Rd 3, 33
I am trying to join this table with another table that I have so that the ID is carried over, but the issue I am running in to is that my join result is getting a larger number of rows than desired simply because it is creating a row for each unique ID that a key has. Is there a way to do the JOIN in a way where it groups each id together (perhaps comma delimited) in one single row?

You can use STRING_AGG:
SELECT t.key, s.count, s.location, STRING_AGG(t.id, ',') as id
FROM YourTable t
JOIN YourTable2 s
ON(t.key = s.key)
GROUP BY t.key, s.count, s.location

Related

Get max value from a joined list paired with another column in DB2

I have the following tables:
Table I:
etu | nr |
1 2
2 2
2 3
2 1
3 4
3 9
Table A:
etu | rsp | nr
2 8 2
2 7 3
2 3 1
3 2 4
3 6 9
Now what I want to have as a result table is
etu | nr | rsp
2.. 3 7
3.. 9 6
So etu and nr are linked together and if multiple equal etu entries are available only the one with the highest nr is taken and the rsp value is added in the result table. in addition if more etu entries are available in the table I there are .. added to the etu value.
Explain: For the 3 9 6 row: The last row on table I is 3 9 so 3 is the number that is looked for and 9 is the highest number for the 3 rows. So we take that and add the rsp value for that ( 6 ) and we add that to the result table. For the 2 row it is the same 2 3 being the highest 2 row in table I.
I got something like:
select x.etu, x.rsp, y.nr from(
select i.etu etu, max(i.nr) maxnr, a.rsp from i left join a on
i.etu=a.etu and i.nr=a.nr group by etu)t
inner join a x on x.etu=t.etu and x.nr=t.nr inner join y on y.etu=t.etu
and y.nr=t.nr
or
select i.etu, max(i.nr) a.rsp from i left join a on i.etu=a.etu and
i.nr=a.nr grounp by
None even get me close to get the results that I want less add the .. after the etu when having the right result.
The system is DB10.5 Windows.
Thank you for all your help in advance.
Viking
I would use a CTE here like this:
with tmp as (
select i.etu, max(i.nr) as nt, count(*) as cnt
from i
group by i.etu)
select case
when tmp.cnt = 1 then char(a.etu)
else concat(rtrim(char(a.etu)), '..')
end as etu,
a.nr,
a.rsp
from tmp
left outer join a
on a.etu = tmp.etu
and a.nr = tmp.nr
The CTE provides the information necessary to join with a to get the correct response, and append the .. as necessary.

oracle - sql query

I have 2 tables
table A has
id, ans_id, ans_value
1 12 social test
2 15 math test
3 14 English test
Table B has
id, quest_id, question_value
3 10 ELA
4 11 history
5 12 math counts
I know that
question id 10 from table B is equal to ans_id 14 in table A
question id 11 from table B is equal to ans_id 12 in table A
question id 12 from table B is equal to ans_id 15 in table A
so my output result should display
quest_id quest_value ans_id, ans_value
10 ELA 14 English Test
11 History 12 Social Test
12 Math Counts 15 Math Test
Please help me with the sql.
thanks
Your current schema is lacking information relating the two tables. In the absence of this, you could create a bridge table, say tablec, which links the questions in tableb to the answers in tablea, e.g.
quest_id | ans_id
10 | 14
11 | 12
12 | 15
Then you could join as follows:
SELECT t1.quest_id,
t1.question_value AS quest_value,
t3.ans_id,
t3.ans_value
FROM tableb t1
INNER JOIN tablec t2
ON t1.quest_id = t2.quest_id
INNER JOIN tablea t3
ON t2.ans_id = t3.ans_id

inserting sql with loop

I have the table PERSONAL
ID_PERS NAME
---------------
11 azerty
22 uiop
and the table TOURNE_LABEL
ID_TOUR NAME
--------------
1 w
2 p
3 v
I want to loop over all of person and then join it with tourne and insert to a new table.
I have created empty table LS_PDA
ID_PERS ID_TOURN
-------------------
11 1
11 2
11 3
22 1
22 2
22 3
how can I do that ?
SQL is all about set based operations. If you're thinking about a loop, chances are you're heading in the wrong direction. For this problem, you could cross-join the tables, thus producing all the possible combinations, and use the insert-select syntax:
INSERT INTO ls_pda
SELECT id_pres, id_tour
FROM personal
CROSS JOIN tourne_label

Return Only Primary Keys That Share The Same Foriegn Keys [duplicate]

This question already has answers here:
Select group of rows that match all items in a list
(3 answers)
Closed 7 years ago.
We're struggling with a lightweight way to reduce results in a larger population of search results by excluding rows that don't match ALL of the foreign keys in a second table.
For example, we have a mapping table that matches documents to tags where each document can have an unlimited number of tag relationships:
DocID | TagID
12 | 1
12 | 2
34 | 1
53 | 1
53 | 4
66 | 1
66 | 2
67 | 3
We're building a table in our SPROC based on a list of tagIDs passed in by the user, so we have a second table that looks like this:
TagID
1
2
What we'd like to do is return only the rows from the first table that contain a match on every value in the second table, effectively an "and" query. So if the user passes in tag values 1 & 2 we want to return DocID 12 and 66. Right now our joins return essentially an "or" result, so values 1 & 2 would return DocIDs 12, 34, and 66.
We're currently stuck with MS SQL 2008R2.
You can do this with group by and having and a twist:
select docid
from firsttable t1 join
secondtable t2
on t1.tagid = t2.tagid
group by docid
having count(*) = (select count(*) from secondtable);
You may need count(distinct) if either table could have duplicates.

sqlquery insert data from one table to other with id from columnname

I have an old database with some complex joining of the data. As given below
Subjects
Id Name
-------------------------------
1 Math
2 Science
3 English
Results
Id StudentId Math MathMax Science ScienceMax English EnglishMax TotalMarks Max
-----------------------------------------------------------------------------------------
1 81 5 10 6 10 3 10 14 30
2 82 8 10 8 10 9 10 25 30
3 83 7 10 8 10 7 10 22 30
Now I am trying to convert it to more easy and readable database. So I come up with the tables like
Results
ResultId StudentId TotalMarks MaxMarks
-------------------------------------------
1 81 14 30
2 82 25 30
3 83 22 30
ResultDetails
Id ResultId SubjectId Marks MaxMarks
--------------------------------------------------------
1 1 1 5 10
2 1 2 6 10
3 1 3 7 10
& so one
Now the real question I can insert data in the new Results table but I am confused on the second table. I can't understand that how to pass column name of one table and get the id of that name from second table and insert it in the third one.
I am trying on but can't understand the right commands to achieve this. My database already have 50000+ records and I have to merge them according to this new tables.
Assuming this is a one-off conversion of data, and you've already populated your new Results table, something as simple as the following should work:
INSERT INTO ResultDetails(ResultId, SubjectId, Marks, MaxMarks)
SELECT
R.StudentId,
1 AS SubjectId,
OldR.Math AS Marks,
OldR.MathMax AS MaxMarks
FROM Results R
INNER JOIN OldResults OldR ON R.StudentId = OldR.StudentId
INSERT INTO ResultDetails(ResultId, SubjectId, Marks, MaxMarks)
SELECT
R.StudentId,
2 AS SubjectId,
OldR.Science AS Marks,
OldR.ScienceMax AS MaxMarks
FROM Results R
INNER JOIN OldResults OldR ON R.StudentId = OldR.StudentId
INSERT INTO ResultDetails(ResultId, SubjectId, Marks, MaxMarks)
SELECT
R.StudentId,
3 AS SubjectId,
OldR.English AS Marks,
OldR.EnglishMax AS MaxMarks
FROM Results R
INNER JOIN OldResults OldR ON R.StudentId = OldR.StudentId
It's not a very elegant solution, but it doesn't need to be for a one-off conversion.