SQL query optimization join union distinct - mysql

I have a query:
Select A.col1 as col1, B.col5 as col2, C.col10 as col3
FROM Table A
JOIN Table B on(A.col2 = B.col2)
JOIN table C on(C.col1 = B.col3)
UNION
SELECT A.col1 as col1, B.col5 as col2, NULL as col3
FROM Table A
JOIN Table B on (A.col2 = B. col2)
where A.col4 != 'somevalue'
Any way of making this faster??
Table A
--------
col1 col2 col4
gerry 1 'somevalue'
harry 2 'othervalue'
tom 3
sarah 4 'somevalue'
col2 of table A is the primary key
Table B
-------
col2 col3 col5
1 45 34
1 34 23
1 56 67
2 34 56
Primary key of B is (col2, col3)
Table C
-------
col1 col10
34 'heyya'
467 'tyga'
56 'pity'
Primary key of C is also composite. one of these keys is col1
Output:
col1 col2 col3
gerry 23 'heyya'
gerry 67 'pity'
gerry 34 NULL
harry 56 'heyya'
So values of B that have presence in C or have 'somevalue' in A are called. Also values having both are also called.

is this OK for you ? so you get all rows and if A.col4 <> 'somevalue' then you get NULL for col3
Select
A.col1 as col1
, B.col5 as col2
, C.col10 as col3
, if(A.col4 != 'somevalue', 1, 0) as col4
FROM Table A
JOIN Table B on(A.col2 = B.col2)
JOIN table C on(C.col1 = A.col3);

Related

Update values from NULL to specific value stored in same table

I am a newbie to SQL so need help and suggestion on one thing which i came across.
My table looks like this:
Col1 Col2 Col3 Col4
1 AA BB NULL
2 AA BB NULL
3 AA BB 1000
4 CC DD NULL
5 CC DD 2000
I want to update the NULL values of Col4 with respective value at Col4 where Col2 and col3 values are same.
Like in my first row Col4 is having NULL while in 3rd row Col4 has value (with same Col1 and Col2 value)
I just want to know is there any way that I can update the NULL with specific values.
update your_table t1
join
(
select col2, col3, max(col4) as col4
from your_table
group by col2, col3
) t2 on t1.col2 = t2.col2 and t1.col3 = t2.col3
set t1.col4 = t2.col4
where t1.col4 is null
You can do this using a join:
update table t join
(select col2, col3, max(col4) as col4
from table t
group by col2, col3
) tt
on t.col2 = tt.col2 and t.col3 = tt.col3
set t.col4 = tt.col4
where t.col4 is null;
Note: this chooses the maximum value of col4 assuming that multiple rows have values.

MySql case statement returning multiple rows and multiple columns

I have a table
-id --col_1 -- col_2 -- col3 --col_4 -- col5
------------------------------------------------
1 a b c d e
2 a1 b1 c1 d1 e1
3 a2 b2 c2 d2 e2
I need to check if col3 contains a value, if present i need to display col1 and col2 values and remaining values should be empty. Another condition if col4 contains value, i need to display only col2 and col5 values
-id --col_1 -- col_2 -- col3 --col_4 -- col5
------------------------------------------------
1 a b c
1 b1 d1 e1
2 a1 b1 c1
2 b1 d1 e1
3 a2 b2 c2
3 b2 d2 e2
I am unaware of which procedure to follow to achieve my requirement. I have used case statement, i have retrieved only one record for two conditions with only one column
SELECT
CASE
WHEN col3 != '' THEN col4
END as a,
CASE
WHEN col4 != '' THEN col2
END as b
FROM table;
Any Help!..
If I understand correctly, you just want union all:
select id, col1, col2, col3, NULL as col4, NULL as col5
from table
union all
select id, NULL, col2, NULL, col4, NULL as col5
from table ;

select a field values that are not found in another table

I need a query which should results a fields that are not found in another table. Let say,
table 1:
comp col1 col2 col3 col4
----------------------------------
nam1 1 1 b c
nam2 0 0 abc c
nam3 1 1 a c
nam4 1 1 b c
nam5 0 0 c c
table2:
name col1 col2
----------------------
b 3 f
a 4 f
c 5 f
result:
comp col3 col4
----------------------
nam2 abc c
the result be based on col3,col1=0,col2=0 on first table and name in second table..abc is not found in table2...
thanks in advance.
The question is not very clear, but if I understood you correctly, you want to select all rows from table1 where col1 and col2 are both 0, and col3 is not contained in the name column of table2. If so, your query should be simple enough:
SELECT comp, col3, col4
FROM table1
WHERE col1 = 0
AND col2 = 0
AND col3 NOT IN (SELECT name FROM table2);
As per the explanation the joining key between table1 and table2 is
table1.col3 = table2.name
Using this you can use the following query
select
t1.comp,
t1.col3,
t1.col4
from table1 t1
left join table2 t2 on t2.name = t1.col3
where t2.name is null

Show only differences between two rows in mysql

Having a (MySQL) audit table containing rows that are similar, is it possible to view only those columns that have different values?
For example, a table containing four columns where column key is primary key, and column id is the identifier to match rows:
key id col1 col2
1 123 B C
2 123 A C
3 456 B C
4 789 B A
5 789 B B
6 987 A C
In the example above I need the query to return only row 1, 2, 4, and 5 as they have matching id, and differing values in col1 and col2, ie B,A and B,A.
key id col1 col2
1 123 B
2 123 A
4 789 A
5 789 B
I know it might not be very efficient solution, but gives what you want. HERE try this:
SELECT A.ID, (CASE A.col1 WHEN B.col1 THEN NULL ELSE B.col1 END), (CASE A.col2 WHEN B.col2 THEN NULL ELSE B.col2 END) FROM tblName A
FULL OUTER JOIN tblName B
ON
A.ID=B.ID
WHERE
(A.col1=B.col1 AND A.Col2<>B.Col2)
OR
(A.col2<>B.col2 AND A.Col1=B.Col1)
INNER JOIN should give same result
This is a bit contrived, in the sense that adding more rows will give very different results - but anyway...
SELECT x.my_key
, x.id
, IF(y.col1=x.col1,'',x.col1) col1
, IF(y.col2=x.col2,'',x.col2) col2
FROM my_table x
JOIN my_table y
ON y.id = x.id
AND y.my_key <> x.my_key
WHERE (y.col1 <> x.col1 OR y.col2 <> x.col2)
ORDER
BY my_key;
Thanks for all responses which guided me.
Using your suggestions I made the sql like this:
SELECT
T1.KEY,
T1.ID,
CASE T2.COL1_DISTINCT_VALUES WHEN 1 THEN NULL ELSE T1.COL1 END AS COL1,
CASE T2.COL2_DISTINCT_VALUES WHEN 1 THEN NULL ELSE T1.COL2 END AS COL2
FROM
TAB1 T1
INNER JOIN
(
SELECT
ID,
COUNT(DISTINCT COL1) AS COL1_DISTINCT_VALUES,
COUNT(DISTINCT COL2) AS COL2_DISTINCT_VALUES
FROM
TAB1
GROUP BY
ID
) T2
ON T1.ID=T2.ID
WHERE
T2.COL1_DISTINCT_VALUES > 1
OR T2.COL2_DISTINCT_VALUES > 1
ORDER BY
KEY,ID;

count duplicate column values in one row

i have a denormalized table, where i have to count the number of same values in other columns.
I'm using the InfiniDB Mysql Storage Engine.
This is my Table:
col1 | col2 | col3
------------------
A | B | B
A | B | C
A | A | A
This is what i expect:
col1Values | col2Values | col3Values
------------------------------------
1 | 2 | 2 -- Because B is in Col2 and Col3
1 | 1 | 1
3 | 3 | 3
Is there something like
-- function count_values(needle, haystack1, ...haystackN)
select count_values(col1, col1, col2, col3) as col1values -- col1 is needle
, count_values(col2, col1, col2, col3) as col2values -- col2 is needle
, count_values(col3, col1, col2, col3) as col3values -- col3 is needle
from table
or am i missing something simple that will do the trick? :-)
Thanks in advance
Roman
select
CASE WHEN col1 = col2 and col1=col3 THEN '3'
WHEN col1 = col2 or col1=col3 THEN '2'
WHEN col1 != col2 and col1!=col3 THEN '1'
ELSE '0' END AS col1_values,
CASE WHEN col2 = col1 and col2=col3 THEN '3'
WHEN col2 = col1 or col2=col3 THEN '2'
WHEN col2 != col1 and col2!=col3 THEN '1'
ELSE '0' END AS col2_values,
CASE WHEN col3 = col1 and col3=col2 THEN '3'
WHEN col3 = col1 or col3=col2 THEN '2'
WHEN col3 != col1 and col3!=col2 THEN '1'
ELSE '0' END AS col3_values
FROM table_name
fiddle demo
Assuming the table has got a key, you could:
Unpivot the table.
Join the unpivoted dataset back to the original.
For every column in the original, count matches against the unpivoted column.
Here's how the above could be implemented:
SELECT
COUNT(t.col1 = s.col OR NULL) AS col1Values,
COUNT(t.col2 = s.col OR NULL) AS col2Values,
COUNT(t.col3 = s.col OR NULL) AS col3Values
FROM atable t
INNER JOIN (
SELECT
t.id,
CASE colind
WHEN 1 THEN t.col1
WHEN 2 THEN t.col2
WHEN 3 THEN t.col3
END AS col
FROM atable t
CROSS JOIN (SELECT 1 AS colind UNION ALL SELECT 2 UNION ALL SELECT 3) x
) s ON t.id = s.id
GROUP BY t.id
;
The subquery uses a cross join to unpivot the table. The id column is a key column. The OR NULL bit is explained in this answer.
I have found a different, very very simple solution :-)
select if(col1=col1,1,0) + if(col2=col1,1,0) + if(col3=col1,1,0) as col1values -- col1 is needle
from table