SQL query grouping dynamic value - sql

I need your help how to summarize from grouping dataset.
docno
acc
doc1
A
doc1
B
doc2
B
doc2
C
doc3
A
doc3
B
doc4
A
doc4
B
The output number 1, I want to expect is:
acc_combined
docno
A;B
doc1
B;C
doc2
A;B
doc3
A;B
doc4
The output number 2:
acc_combined
count
A;B
3
B;C
1
Column acc_combined can be dynamic value such as D;E, A;B;C, C;D;E, A;E, etc.

To get the output you're looking for, where StackOverflow is a table formatted according to the first table you provided (accept I accidentally misspelled acc as accn, my bad):
WITH First_CTE AS (
SELECT docno,
STRING_AGG(accn, ';') AS acc_combined
FROM StackOverflow
GROUP BY docno
) SELECT acc_combined,
COUNT(docno) AS count
FROM First_CTE
GROUP BY acc_combined

Related

SQL query - Cumulatively concatenate strings in consecutive rows

I'm a data analyst, so I write SQL queries to retrieve data from a database. I'm not sure what kind of SQL exactly, just assume the most standard (also not things like 'DECLARE #tbl', and no create functions etc.)
Here is my problem.
Given the following table:
name
number
letter
A
1
a
A
2
b
A
3
c
A
4
d
B
1
a
B
2
b
B
3
c
B
4
d
I want the following result: (concatenate letter cumulatively, order by number))
name
number
letter
result
A
1
a
a
A
2
b
a,b
A
3
c
a,b,c
A
4
d
a,b,c,d
B
1
a
a
B
2
b
a,b
B
3
c
a,b,c
B
4
d
a,b,c,d
Any help is highly appreciated. Thanks very much.
This answers the original version of the question which was tagged MySQL.
MySQL doesn't support group_concat() as a window function. So a subquery may be your best alternative:
select t.*,
(select group_concat(t2.letter order by t2.number)
from t t2
where t2.name = t.name and t2.number <= t.number
) as letters
from t;

Select data with latest date for each id

I am currently working on Microsoft Access an I am struggling to do what I want.
I have this table A:
Table A
id title name date
123 azer dfgd 1
123 afg qsd 5
123 arr poi 7
123 aur qhg 3
456 aoe aer 3
456 iuy zer 4
And I would like to get the columns id,title and name that have the latest date (highest number) for each id
With that example, the query would give
id title name date
123 arr poi 7
456 iuy zer 4
I hope you'll be able to help me.
Thanks in advance !
I would recommend a correlated subquery:
select a.*
from a
where a.date = (select max(a2.date) from a as a2 where a2.id = a.id);
For performance, you want an index on a(id, date).
With NOT EXISTS:
select t.*
from tablename t
where not exists (
select 1 from tablename
where id = t.id and date > t.date
)

SQL query- help in implementation

I have two tables: Member and Document
Member table:
Memberkey(Key) Member country
-------------- ---------------
111 Aus
222 US
333 Germany
444 Chile
Document table:
Memberkey(notNULL) doc_type_cd doc_cat_cd docname
---------------- ----------- ---------- -------------
111 1 1 Sales_doc
222 2 1 Finance_doc
222 3 3 Legal_doc
333 3 3 Legal_doc
444 2 1 Finance doc
444 3 3 Legal_doc
My requirement is to fetch memberkey, member country, and doc_name only if the document is legal_doc (i.e. doc_type_cd = 3 and doc_cat_cd =3). If no such document exists for a member, then this should come as null.
Output:
Memberkey member country doc_name
---------- -------------- -----------
111 aus NULL
222 US Legal_doc
333 Germany Legal_doc
444 Chile Legal_doc
How can I achieve this? If I use condition on doc_type_cd and doc_cat_cd in the query, then those members will be skipped, who have no legal_doc (111 in this example). Also, if a member has no entry in "document" table, then it should also be shown with member key, country and documentname(NULL in this case). Is there any effcient way to achieve this?
Please help. Thanks!
You need a left join for your requirement. By left joining on the three conditions below you will get a record for every member, and if they do have a legal document than that will be populated in the doc_name column, and if they do not have a legal document than the value will be null.
SELECT M.MemberKey, M.[member country], D.doc_name
FROM Member M
LEFT JOIN Document D ON
M.MemberKey = D.MemberKey AND
D.doc_type_cd = 3 AND
D.doc_cat_cd = 3
Here is a solution in MSSQL:
SELECT
M.MemberKey
, M.MemberCountry
, DCA.DocName
FROM
[Member] M
OUTER APPLY (
SELECT
D.DocName
FROM
[Document] D
WHERE
D.MemberKey = M.MemberKey
AND D.doc_type_cd = 3
AND D.doc_cat_cd =3
) DCA
Please note, that this query will retrieve multiple rows if there are multiple legal documents. If you want to get the first document, add TOP(1) to the subquery.
You want to use a case statement, and test for doc_type_cd or doc_cat_cd, like this:
select memberkey,
[member country],
case when doc_type_cd = 3 or doc_cat_cd = 3 then doc_name else null end
from memberTable mt
left outer join documentTable dt
on mt.memberKey = dt.memberKey
Here is another solution which could run on most RDBMS:
-- Query to get all members with legal document
SELECT
M.MemberKey
, M.MemberCountry
, D.DocName
FROM
Member M
INNER JOIN Document D
ON M.MemberKey = D.MemberKey
WHERE
D.doc_type_cd = 3
AND D.doc_cat_cd =3
UNION ALL
-- Query to get all members without legal document
SELECT
M.MemberKey
, M.MemberCountry
, NULL AS DocName
FROM
Member M
WHERE
NOT EXISTS (SELECT 1 FROM Document D WHERE D.MemberKey = M.MemberKey AND D.doc_type_cd = 3 AND D.doc_cat_cd = 3)

SQL JOIN WHERE IN STRING OF OTHER TABLE

I need to join two tables together where the seccond table has one of the first tables in a string.
e.g
Table1 has ID1, ID2, Lang_id, User, Text.
Table2 has ID_a, User, List_ID2.
Additionally, the List_ID2 is comma seperated, so I have to make sure I get it in all cases, so if it is the only number, or the at beginning, middle or end of the string. BUT NOT truncate the values, i.e. (10 is not 100 - '10'0)
The extra kicker is that Lang_id is the language of the Place and I also have to seperate that.
I have the language seperated fine, I can't get the ID_a into my results
i.e
TABLE 1
ID1 ID2 Lang_id User Text
1 2 1 bob Me
1 2 2 bob Mich
1 2 3 bob Mi
2 1 1 bob You
2 1 2 bob Du
2 1 3 bob usted
3 1 1 tim You
3 1 2 tim Dich
3 1 3 tim le
4 3 1 tim Hello
4 3 2 tim Hallo
4 3 3 tim ihola
TABLE 2
ID_a User List_ID2
100 bob 1, 2
200 tim 1, 3
RESULTS
ID_a ID1 ID2 English German Spanish
100 1 1 You Du usted
100 2 2 Me Mich Mi
200 3 1 You Dich le
200 4 3 Hello Hallo ihola
My statement looks a little like this:
SELECT DISTINCT main.ID1, main.ID2, ID_a
(SELECT Text
FROM table1 AS a
WHERE lang_id = 1
AND main.ID1 = a.ID1
AND main.ID2 = a.ID2) AS English,
(SELECT Text
FROM table1 AS b
WHERE lang_id = 2
AND main.ID1 = b.ID1
AND main.ID2 = b.ID2) AS German,
(SELECT Text
FROM table1 AS c
WHERE lang_id = 3
AND main.ID1 = c.ID1
AND main.ID2 = c.ID2) AS Spanish,
FROM table1 AS main
LEFT OUTER JOIN table2 ON table2.User = main.User
AND (table2.List_ID2 LIKE STR(ID2)
OR table2.List_ID2 LIKE (ID2 + ',%')
OR table2.List_ID2 LIKE ('%,' + ID2 + ',%')
OR table2.List_ID2 LIKE ('%,' + ID2)
The first part is working fine (the language is seperated), but I can't get the ID from table2, I've tried a few differnt methods, and the above comes back without an error, but alot of NULL values.
Found the answer here:
SQL STR() function equality
I needed to specify the Length of the STR()

MySql Select Query

I have 2 tables like this
Table 1
Id f1 f2
1 ABC red,green
2 DEF blue,yellow
Table 2
id color value
1 red r
2 green g
3 blue b
4 yellow y
How Can I get result like this
f1 f2 values
ABC red,green r,g
DEF blue,yellow b,y
Thanks in Advance
Use the GROUP_CONCAT function:
SELECT t1.f1,
t1.f2,
GROUP_CONCAT(t2.value) AS values
FROM TABLE_1 t1
JOIN TABLE_2 t2 ON FIND_IN_SET(t2.color, t1.f2)
GROUP BY t1.f1, t1.f2
Can you adjust the schema? I think it would benefit if you had a mapping table of whatever ABC is to the colors.
EG:
mapping_table
------------
id table1_id table2_id
1 1 1
2 1 2
That way you can easily do a JOIN.