Minimum values from the table - mysql

I need the minimum value from 3 coloumn and corresponding name for the min value,
like this..
Name val1 val2 val3
a 12 5 4
b 10 9 1
c 7 11 5
d 13 8 2
output:
Name MIN
b 1
I wrote query to find minimum value :
select MIN(less)
from (
select case
when val1<=val2 and val1<=val3 then val1
when val2<=val1 and val2<=val3 then val2
when val3<=val1 and val3<=val2 then val3 end as less from table) as low
I used alises,i want to display the corresponding name from the table...plz tell me the query...

You can do it using the UNION operator to convert the 3 column table into a single table with 1 column.
SELECT TOP 1 Name, Val AS Min
FROM (
SELECT Name, val1 AS Val
FROM table
UNION
SELECT Name, val2 AS Val
FROM table
UNION
SELECT Name, val3 AS Val
FROM table
) AS sub_query
ORDER BY Val ASC
This solution has the added advantage that it is easier to maintain if the number of columns increases.

Most Concise
SELECT top 1 Name,col,val
FROM T
UNPIVOT ( val for col in (val1,val2,val3)) unpvt
ORDER BY val
Most Efficient (assuming these columns are indexed)
;WITH cte(Name, col, val) AS
(
SELECT TOP 1 Name, 'val1', val1
FROM T
ORDER BY val1
UNION ALL
SELECT TOP 1 Name, 'val2', val2
FROM T
ORDER BY val2
UNION ALL
SELECT TOP 1 Name, 'val3', val3
FROM T
ORDER BY val3
)
SELECT TOP 1 Name, col, val
FROM cte
ORDER BY val

Related

how to combine multiple rows into one row?

My table:
id val
--------
a 1
a 2
a 3
b 7
b 8
b 9
b 10
What i want to get is:
id val1 val2 val3 val4
--------------------------
a 1 2 3 null
b 7 8 9 10
Is there any simple way for this?
If you are using MySQL 8+, then ROW_NUMBER combined with pivoting logic provides one way:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY val) rn
FROM yourTable
)
SELECT
id,
MAX(CASE WHEN rn = 1 THEN val END) AS val1,
MAX(CASE WHEN rn = 2 THEN val END) AS val2,
MAX(CASE WHEN rn = 3 THEN val END) AS val3,
MAX(CASE WHEN rn = 4 THEN val END) AS val4
FROM cte
GROUP BY
id;
Not quite the same output, but worth considering:
SELECT id, GROUP_CONCAT(val)
FROM tbl GROUP BY id;

Match duplicate value from 2 colums and 1 unique value from 1 column mysql

I have this table, here is my db Fiddle
CREATE TABLE table1 (
`ID` VARCHAR(100),
`Val` VARCHAR(100),
`Val2` VARCHAR(100),
`Val3` VARCHAR(100)
);
INSERT INTO table1
(`ID`, `Val`, `Val2`, `Val3`)
VALUES
('1','100','200','90'),
('2','100','200','10'),
('3','100','200','20'),
('4','20','100','55'),
('5','20','100','10'),
('6','112','100','20'),
('7','112','100','20'),
('8','90','200','90'),
('9','30','90','180'),
('10','30','90','29');
I want the result with this condition
Val had to be duplicate AND
Val2 had to be duplicate AND
After i got the duplicate value, now i need to check the val3 from the duplicate value if the value of val3 had unique value from the previous aggregate
i tried with this query
SELECT
t1.*
FROM
table1 t1
WHERE
EXISTS (
SELECT
1
FROM
table1
WHERE
ID <> t1.ID
AND Val = t1.Val
AND Val2 = t1.Val2
)
AND NOT EXISTS (
SELECT
1
FROM
table1
WHERE
Val = t1.Val
AND Val2 = t1.Val2
AND Val3 IN (
SELECT Val3
FROM table1
GROUP BY Val3
HAVING count( * ) > 1
)
)
I expect the result would be like this
ID Val Val2 Val3
1 100 200 90
2 100 200 10
3 100 200 20
4 20 100 55
5 20 100 10
9 30 90 180
10 30 90 29
BUt i got the result like this
ID Val Val2 Val3
9 30 90 180
10 30 90 29
Sample 2
INSERT INTO table1
(`ID`, `Val`, `Val2`, `Val3`)
VALUES
('1','100','200','90'),
('2','100','200','10'),
('3','100','200','20'),
('19','100','200','20'),
('4','20','100','55'),
('5','20','100','10'),
('6','112','100','20'),
('7','112','100','20'),
('8','90','200','90'),
('9','30','90','180'),
('10','30','90','29');
Expected result 2
ID Val Val2 Val3
1 100 200 90
2 100 200 10
4 20 100 55
5 20 100 10
9 30 90 180
10 30 90 29
dbfiddle 2
Sample 3
INSERT INTO table1
(`ID`, `Val`, `Val2`, `Val3`)
VALUES
('1','100','200','aa'),
('2','100','200','aa'),
('3','100','200','aa'),
('19','100','200','ab'),
('4','20','100','SD2'),
('5','20','100','SD1'),
('6','112','100','aa'),
('7','112','100','ab'),
('8','90','200','aa'),
('9','30','90','SF2'),
('10','30','90','SF1');
Expected result 3
ID Val Val2 Val3
4 20 100 SD2
5 20 100 SD1
6 112 100 aa
7 112 100 ab
9 30 90 SF2
10 30 90 SF1
Some people might be confused with sample 3, so here is a notes for sample 3 :
For this case, ID 19 in sample 3 had same value with column val and val2 for id 1, 2, 3 ( 100 and 200), but these id (1, 2, 3) had same aa value in val3, so id 1,2,3 must be excluded, because these id did not match with last condition (val, val2, val3) is unique. ID 19 is fine but val dan val2 column that had duplicate value which is id 1,2,and 3 had already excluded, it makes id 19 had no duplicate value for both column val and val2. if there was another data like '200','100','200','ae' in sample 3, the id 19 will included in result because it has duplicate value beside id 1,2,and 3.
for sample 3 ID 19 will be included if the data in table1 were like this
Sample 3 ( different case )
INSERT INTO table1
(`ID`, `Val`, `Val2`, `Val3`)
VALUES
('1','100','200','aa'),
('2','100','200','aa'),
('3','100','200','aa'),
('19','100','200','ab'),
('200','100','200','ae'),
('4','20','100','SD2'),
('5','20','100','SD1'),
('6','112','100','aa'),
('7','112','100','ab'),
('8','90','200','aa'),
('9','30','90','SF2'),
('10','30','90','SF1');
The expected result will be like this
ID Val Val2 Val3
4 20 100 SD2
5 20 100 SD1
19 100 200 ab
200 100 200 ae
6 112 100 aa
7 112 100 ab
9 30 90 SF2
10 30 90 SF1
Join the table to the queries that apply your conditions:
select distinct t.*
from (
select val, val2
from table1
group by val, val2
having count(*) > 1
) t1
inner join (
select val, val2, val3
from table1
group by val, val2, val3
having count(*) = 1
) t2
on t2.val = t1.val and t2.val2 = t1.val2
inner join (
select val, val2, val3
from table1
group by val, val2, val3
having count(*) = 1
) t3
on t3.val = t1.val and t3.val2 = t1.val2 and t3.val3 <> t2.val3
inner join table1 t on t2.val = t.val and t2.val2 = t.val2 and t.val3 in (t2.val3, t3.val3)
See demo1, demo2, demo3, demo4.
As I understand your question, you want rows whose (val, val2) tuple is not unique, and whose (val, val2, val3) is unique.
Here is one way to express this by filtering the dataset with correlated subquery:
select t1.*
from table1 t1
where
(
select count(*)
from table1 t2
where t2.val = t1.val and t2.val2 = t1.val2
) > 1
and (
select count(*)
from table1 t2
where t2.val = t1.val and t2.val2 = t1.val2 and t2.val3 = t1.val3
) = 1
order by id
For performance, consider an index on (val, val1, val2) (the ordering of columns in the index matters here).
If you are lucky enough to be running MySQL 8.0, this can be phrased more simply and more efficiently using window functions:
select id, val, val2, val3
from (
select
t1.*,
count(*) over(partition by val, val2) cnt_1,
count(*) over(partition by val, val2, val3) cnt_2
from table1 t1
) t
where cnt_1 > 1 and cnt_2 = 1
As #GMB told in rather simplified manner in his answer, you want rows whose (val, val2) tuple is not unique, and whose (val, val2, val3) is unique.
Following query should accomplish that very easily:
select t.*
from table1 t
inner join
(
select t1.val, t1.val2
from table1 t1
inner join
(select val,val2,val3
from table1
group by val,val2,val3
having count(val3) = 1
) t2
on t1.val = t2.val and t1.val2 = t2.val2 and t1.val3 = t2.val3
group by t1.val, t1.val2
having count(distinct t1.id) > 1
) tmp
on tmp.val = t.val and tmp.val2 = t.val2
inner join
(select val,val2,val3
from table1
group by val,val2,val3
having count(val3) = 1
) t3
on t.val = t3.val and t.val2 = t3.val2 and t.val3 = t3.val3
Please find the fiddle link for Sample1, Sample2, Sample3 and Sample4.

SQL Select rows where col1 or col2 equals variable

So I want to select rows from table where col1 or col2 equals to variable, but if there is already row selected where col1 equals to variable (variable X) and col2 is anything else (variable Y) then it won't select another row where col2 equals to variable X and col1 equals to that variable Y. Everything ordered by column TIME descending.
Let's say this is my table:
COL1 COL2 TIME COL4
1 2 0 A
1 2 1 B
2 1 2 C
1 3 3 D
3 1 4 E
4 2 5 F
3 4 6 G
1 2 7 H
4 1 8 I
And let's say that variable X equals to 1, then I want to have these rows:
COL1 COL2 TIME COL4
4 1 8 I
1 2 7 H
3 1 4 E
So it won't show me this row
COL1 COL2 TIME COL4
2 1 2 C
because there is already a combination where col1/col2 is 2/1 or 1/2.
Sorry if I explained it in a bad way, but I can't think of better explanation.
Thank you guys.
Making a couple of key assumptions...
SELECT a.*
FROM my_table a
JOIN
( SELECT MAX(time) time
FROM my_table
WHERE 1 IN (COL1,COL2)
GROUP
BY LEAST(col1,col2)
, GREATEST(col1,col2)
) b
ON b.time = a.time;
EDIT: I posted this answer when it was thought that OP's database was SQL Server. But as it turns out, the database is MySQL.
I think this query should do it:
select t.col1, t.col2, t.time, t.col4
from (select t.*,
row_number() over (
partition by
case when col1 < col2 then col1 else col2 end,
case when col1 < col2 then col2 else col1 end
order by time desc) as rn
from tbl t
where t.col1 = x or t.col2 = x) t
where t.rn = 1
order by t.time desc
The key part is defining the row_number partition by clause in such a way that (1, 2) is considered equivalent to (2, 1), which is what the case statements do. Once the partitioning works correctly, you just need to keep the first row of every "partition" (where t.rn = 1) to exclude duplicate rows.

How to group repeated row values in a column

t_no name value
1 a 45
1 b 23
1 c 5
1 a 12
1 b 99
1 c 6
I need to show my above table as
no name value1 value2
1 a 45 12
1 b 23 99
1 c 5 6
You can't create dynamic columns in mysql alone, either in scripting language, or you can use group_concat to have them in one column:
SELECT to_no, name, GROUP_CONCAT(value)
FROM table GROUP BY to_no, name
result:
no name value
1 a 45,12
1 b 23,99
1 c 5,6
MySQL does not have a pivot function, but you can use an aggregate function with a CASE expression. Since you have multiple values for each t_no and name, then you could use user defined variables to assign a row number to each group of values:
select t_no, name,
max(case when rn=1 then value end) value1,
max(case when rn=2 then value end) value2
from
(
select t_no, name, value,
#rn:=case when #prev=t_no and #c=name then #rn else 0 end +1 rn,
#prev:=t_no,
#c:=name
from yourtable
cross join (select #rn:=0, #prev:=0, #c:=null) c
order by t_no, name
) d
group by t_no, name
order by t_no, name;
See SQL Fiddle with Demo

How to compare and change values in MYSQL

My table looks like:
[Number] [Value1]
1234567 8
1234567C 7
9876543 1
9876543C 2
5555555 3
5555555C 3
I want to search the entries for same values in the first column (except the "C" in the end of the number) and set the higher value in the second column to the lower one.
There are always only two same values (one with "C") and some pairs have same values in the second column and some have different.
The result of the query should be:
Number Value1
1234567 7
1234567C 7
9876543 1
9876543C 1
5555555 3
5555555C 3
The following is not an ideal solution but should do what you want:
update yourTable
set value1 = (
select min(value1) from (
select * from yourTable
) as x
where yourTable.number = x.number + 'C');
I have tested it with this in mysql workbench:
create table yourTable(number varchar (10),value1 int);
insert into yourTable Values('1234567',8);
insert into yourTable Values('1234567C',7);
insert into yourTable Values('9876543',1);
insert into yourTable Values('9876543C',2);
insert into yourTable Values('5555555',3);
insert into yourTable Values('5555555C',3);
insert into yourTable Values('55555556',10);
insert into yourTable Values('55555556C',2);
Then select * from yourTable;will return:
1234567 8
1234567C 7
9876543 1
9876543C 2
5555555 3
5555555C 3
55555556 10
55555556C 2
After the update select * from yourTable; will return:
1234567 7
1234567C 7
9876543 1
9876543C 1
5555555 3
5555555C 3
55555556 2
55555556C 2
Hope that is what you wanted :)
Actually, you don't need any checking, since there are only 2 values (and thus the query is even simpler):
UPDATE
table
SET
Value1 =
(
SELECT
MAX(Value1)
FROM
table t
WHERE
table.Number = t.Number
OR table.Number = t.Number + 'C'
)
WHERE
RIGHT(Number, 1) != 'C'