MySql Select Query - sql

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.

Related

How to get Oracle to return unique results in a one to many relationship tables with a left join

I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D

SQL query to display list items

Okay, I am trying to write a query from a poor table structure.
Below is something that I want to achieve:
Table 1: List of Items
T1C1 T1C2
A Fred
B Bart
C Carl
Table 2: Second list of Items
T2C1 T2C2
1 Chocolate
2 Cake
3 Pie
4 Fish
5 Pizza
Table 3: Joining table
T3C1 T3C2 T3C3
1 A Y
4 A Y
5 A N
1 B N
2 B Y
5 B Y
1 C Y
2 C N
3 C Y
Result
Select query based on a person in Table 1.
However if the value is not in Table 3 then R1C4 should default to N
R1C1 R1C2 R1C3 R1C4
1 Chocolate A Y
2 Cake A N
3 Pie A N
4 Fish A Y
5 Pizza A N
I've assumed a few details to come up with the following:
DECLARE #UserId CHAR
SET #UserId = 'A'
SELECT T2.T2C1 AS R1C1,
T2.T2C2 AS R1C2,
COALESCE(T3.T3C2, #UserId) AS R1C3,
COALESCE(T3.T3C3, 'N') AS R1C4
FROM Table2 AS T2
LEFT JOIN Table3 AS T3 ON T3.T3C1 = T2.T2C1 AND T3.T3C2 = #UserId
Assumption: example output is for user Fred.
To ensure that we see all entries from Table2 we use a LEFT JOIN on the link table (Table3).
We have to COALESCE the values for the two records that don't exist in the link table.
Note that this only works if we filter to one user, as per the expected output.
View my SQL Fiddle for full example.
declare #filter varchar(1)
select #filter= T1C1 from Table_1 where T1C2='Fred';
with CteResult (R1C1,R1C2,R1C3,R1C4)as
(select T2C1 as R1C1,T2C2 as R1C2,T3C2 as R1C3, T3C3 as R1C4 from table_2 A
inner join Table_3 B on T2C1 =T3C1
where T3C2=#filter)
select T2C1 as R1C1,T2C2 as R1C2,coalesce(R1C3,#filter) as R1C3,
case when R1C4 is null then 'N' else R1C4 end R1C4
from table_2 A left outer join CteResult B
on B.R1C1=A.T2C1

CASE statement when using LEFT JOIN

I need some help in fixing a data aberration. I create a view based on two tables with Left Join and the result has some duplicates (as given in the logic section)
Data Setup:
*******************
TEST1
*******************
PRODUCT VALUE1 KEY
1 2 12
1 3 13
1 4 14
1 5 15
*******************
TEST2
*******************
KEY ATTRIBUTE
12 DESC
13 (null)
14 DESC
15 (null)
What I tried so far
SELECT
B.KEY,
B.ATTRIBUTE,
A.PRODUCT
A.VALUE1
FROM TEST2 B LEFT JOIN TEST1 A ON TEST2.KEY = TEST1.KEY;
What I get with above SQL is
KEY ATTRIBUTE PRODUCT VALUE1
12 DESC 1 2
13 (null) 1 3
14 DESC 1 4
15 (null) 1 5
What I need to get
KEY ATTRIBUTE PRODUCT VALUE1
12 DESC 1 2
13 DESC 1 3
14 DESC 1 4
15 DESC 1 5
Logic:
Since all products with id 1 are same, I need to retain the attributes if it is NULL. So doing a distinct of PRODUCT and ATTRIBUTE will always have 1 row per product id. Test1 has more than 100 products and Test2 has corresponding descriptions.
Note: This is not a normalized design since it is data warehousing. So no complaints on design please
I would like to have a CASE statement in the attribute field.
CASE
WHEN ATTRIBUTE IS NULL THEN {fix goes here}
ELSE ATTRIBUTE
END AS ATTRIBUTE
Some one needs to see fiddle, then go here
It's not clear but if you say that for each product can be only one attribute then try to use MAX() OVER
SELECT
TEST1.Product,
TEST1.value1,
TEST2.KEY,
MAX(ATTRIBUTE) OVER (PARTITION BY test1.Product) ATTR
FROM TEST2
LEFT JOIN
TEST1 ON TEST2.KEY = TEST1.KEY
SQLFiddle demo
SQL Fiddle:
SELECT B.KEY,
CASE WHEN B.ATTRIBUTE IS NULL THEN
(
SELECT s2.ATTRIBUTE
FROM test2 s2
LEFT JOIN TEST1 s1 ON s1.KEY = s2.KEY
WHERE s1.PRODUCT = A.PRODUCT
AND s2.ATTRIBUTE IS NOT NULL
AND ROWNUM = 1
) ELSE B.ATTRIBUTE END AS ATTRIBUTE,
A.PRODUCT, A.VALUE1
FROM TEST2 B
LEFT JOIN TEST1 A ON A.KEY = B.KEY;
SELECT
NVL(attribute,'DESC')
FROM TEST2 LEFT JOIN TEST1 ON TEST2.KEY = TEST1.KEY;
Just seen its Oracle please try above

One select on two tables with NULL and not null

I try to get select from two tables and put some data from one to other with ussing WHERE
(PL/SQL)
I have two tables like those:
table1
ID NAME COLOR COMPANY_SHORT_NR
1 a Green 1
2 b Red 23
3 c Blue null
4 a Green null
5 g Green 1
table2
ID SHORT COMP_NAME
1 1 company_name_1
2 23 comapny_name_2
and now I would like to get all data from table 1 with companies names and if its null get info it is null like that
1 a Green company_name_1
2 b Red comapny_name_2
3 c Blue null
4 a Green null
5 g Green company_name_1
I tried do it like this:
select ID
,NAME
,COLOR
,COMPANY_SHORT_NR
from table1
,table2
where COMPANY_SHORT_NR = SHORT
but this give me only not null values:
1 a Green company_name_1
2 b Red comapny_name_2
5 g Green company_name_1
if i use sth like this:
select ID
,NAME
,COLOR
,COMPANY_SHORT_NR
from table1
,table2
where COMPANY_SHORT_NR = SHORT or COMPANY_SHORT_NR is null
I get thousends of records ...
If I use only IS NULL than it returns me only 2 rows as it should be.
Where I make mistake ?
You have to use left join as below
select ID
,NAME
,COLOR
,COMPANY_SHORT_NR
from table1 t1
left join table2 T2 on t1.COMPANY_SHORT_NR = t2.SHORT
you neen OUTER JOIN for that
select ID
,NAME
,COLOR
,COMPANY_SHORT_NR
from table1
LEFT OUTER JOIN table2 ON ( COMPANY_SHORT_NR = SHORT )
wouldn't it be better to join the tables? like SELECT ID, NAME, COLOR, COMPANY_SHORT_NR FROM table1 t1 LEFT JOIN table2 t2 on t2.SHORT = t1.COMPANY_SHORT_NR WHERE 1

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()