Use variable from selected row on mysql - mysql

I want to use a selected row on mysql like this.
I have a query about value.
Select maxValue from tableOne
And i want to use this value on my query like that.
Select (Select maxValue from tableOne where tableTwo.Aa=tableOne.Aa LIMIT 1) as maxValue,CASE tableTwo.Param WHEN 1 Then maxValue -50
When 2 Then maxValue-100
When 3 Then maxValue-400
When 4 Then maxValue-500
ELSE
maxValue
END ,
from tableTwo
How can i use like this ?

One way to do this is
Select
CASE tableTwo.Param
WHEN 1 Then t.maxValue - 50
When 2 Then t.maxValue - 100
When 3 Then t.maxValue - 400
When 4 Then t.maxValue - 500
ELSE t.maxValue
END
from tableTwo
JOIN
(
SELECT
Aa
, MAX(maxValue)
FROM tableOne
GROUP BY Aa
) t
ON t.Aa = tableTow.Aa

You need one column, so you don't need to join, just select from table that has the column:
(Select maxValue from tableOne where tableTwo.Aa=tableOne.Aa LIMIT 1)
should be
(Select maxValue from tableWithMaxValue LIMIT 1)
and if you want to join tables, you can do this in outer query, so the whole query becomes:
SELECT CASE tableTwo.Param WHEN 1 Then maxValue -50
WHEN 2 Then maxValue-100
WHEN 3 Then maxValue-400
WHEN 4 Then maxValue-500
ELSE maxValue END
FROM tableOne t1
JOIN tableTwo t2 ON t1.Aa = t2.Aa
LIMIT 1;

Related

Calculate average per day based on the difference of the values

I have a table:
value
updated_at
ID
5
2022-1-1 12:00:00
1
10
2022-1-1 12:00:30
2
20
2022-1-1 12:02:30
3
What I want to do is to get an average based on the updated_at column difference, and the values of course.
So, I guess the formula should be:
(sumof((value2 - value1) * (date2 - date1))) / (dateLast - dateFirst) where 1 and 2 means for each two rows when we traverse from the first to the last item. eg for this table we'll have:
First and second row: (value2 - value1) * (date2 - date1) = (10 - 5) * (30 (seconds)) = 150
for second and third row: (20 - 10) * 120 = 1200
So the result is:
(1200 + 150) / (2022-1-1 12:02:30 - 2022-1-1 12:00:00) = 9
I probably can get this working with a self JOIN on ID and ID + 1 and I also can do the diff of last and first date, but I can't do them both in the same query! I have no idea how to do that, is this even possible to be done in a single query?
Update
My MySql version is 5.6
For MySql 8.0+ you can use LAG() window function to get each row's previous values and then aggregate:
WITH cte AS (
SELECT *,
value - LAG(value) OVER (ORDER BY updated_at) dif_value,
UNIX_TIMESTAMP(updated_at) - UNIX_TIMESTAMP(LAG(updated_at) OVER (ORDER BY updated_at)) dif_time
FROM tablename
)
SELECT SUM(dif_value * dif_time) /
(UNIX_TIMESTAMP(MAX(updated_at)) - UNIX_TIMESTAMP(MIN(updated_at))) result
FROM cte;
For previous versions and if there are no gaps between the ids, use a self join:
SELECT SUM(dif_value * dif_time) /
(UNIX_TIMESTAMP(MAX(updated_at)) - UNIX_TIMESTAMP(MIN(updated_at))) result
FROM (
SELECT t1.*,
t1.value - t2.value dif_value,
UNIX_TIMESTAMP(t1.updated_at) - UNIX_TIMESTAMP(t2.updated_at) dif_time
FROM tablename t1 LEFT JOIN tablename t2
ON t1.ID = t2.ID + 1
) t;
See the demo.

Count number of times that columns A & B contain values that also appear in column B & A

In my database, I have a table with those values :
column_a,column_b
1,2
3,4
2,1
4,3
3,1
5,6
1,4
1,3
I'm able to know how many times there's a match between a specific value, and any other value. Take value "1" :
SELECT COUNT(*) FROM (SELECT * FROM `table` WHERE `column_a` = 1) as T1
JOIN (SELECT * FROM `table` WHERE `column_b` = 1) as T2
WHERE T1.`column_b` = T2.`column_a`
Resultat will be 2, because we have 1,2, 2,1, 1,3 and 3,1 -> 1 matches with 2 and 3.
Now, I want to know the total number of matches. Here, it will be 3 (because there's 3,4 and 4,3).
Does anyone have and idea?
Thank you
One way to solve this is to count all the cases where a matching pair is found but restricting the matches such that only the pair where column_ais greater than column_b is selected to avoid duplication:
SELECT COUNT(*)
FROM `table` t1
WHERE EXISTS (
SELECT *
FROM `table` t2
WHERE t2.column_b = t1.column_a AND t2.column_a = t1.column_b
AND t2.column_a < t1.column_a
)
Output:
3
Demo on SQLFiddle
You can also use least() & greatest() function :
SELECT COUNT(*)
FROM (SELECT COUNT(*)
FROM `table` t1
GROUP BY LEAST(column_a, column_B), GREATEST(column_a, column_B)
HAVING COUNT(*) > 1
) t;
Here is a demo.
Here is one method:
select count(distinct case when a = 1 then b else a end)
from t
where 1 in (a, b);
Here is a db<>fiddle.

SQL - Split a column into two columns in Mysql

I have this table. Considering the id starts from 0.
Table 1
ID Letter
1 A
2 B
3 C
4 D
6 E
I need following output
Col1 Col2
NULL A
B C
D NULL
E NULL
I tried using union with id, id - 1 and id + 1, but I couldn't figure out how to get letter based on ids, also tried even odd logic but nothing worked.
Any help is appreciated.
Thank you
You didn't post the database engine, so I'll assume PostgreSQL where the modulus operand is %.
The query should be:
select o.letter, e.letter
from (
select id, letter, id as base from my_table where id % 2 = 0
) o full outer join (
select id, letter, (id - 1) as base from my_table where id % 2 <> 0
) e on e.base = o.base
order by coalesce(o.base, e.base)
Please take the following option with a grain of salt since I don't have a way of testing it in MySQL 5.6. In the absence of a full outer join, you can perform two outer joins, and then you can union them, as in:
select * from (
select o.base, o.letter, e.letter
from (
select id, letter, id as base from my_table where id % 2 = 0
) o left join (
select id, letter, (id - 1) as base from my_table where id % 2 <> 0
) e on e.base = o.base
union
select e.base, o.letter, e.letter
from (
select id, letter, id as base from my_table where id % 2 = 0
) o right join (
select id, letter, (id - 1) as base from my_table where id % 2 <> 0
) e on e.base = o.base
) x
order by base
Just use conditional aggregation:
select max(case when id % 2 = 0 then letter end) as col1,
max(case when id % 2 = 1 then letter end) as col2
from t
group by floor(id / 2);
If you prefer, you can use mod() instead of %. MySQL supports both.

Get Sum of rows of SQL query that satisfies multiple criteria

I have a table and I am trying to get the sum of Col A to 2 decimal places of all rows (there is an id column ID) that satisfies the following:
1) There is another row with a matching Col B
2) It has an unique pair of the values in Col C and Col D
Try this:
SELECT ROUND(SUM(ColA), 2) AS ColA_Sum
FROM datatable t
WHERE EXISTS (
SELECT 1
FROM datatable t2
WHERE t2.ID <> t.ID -- Another row must have different id
AND t2.ColB = t.ColB -- Matching Column B
)
AND EXISTS (
SELECT 1
FROM datatable t3
WHERE t3.ColC = t.ColC -- Same Column C
AND t3.ColD = t.ColD -- Same Column D
HAVING COUNT(*) = 1 -- Only 1 row with such values
)
I think it might be as simple as:
SELECT ROUND(SUM(t.cola), 2) AS cola_sum
FROM t
WHERE cola = colb
AND NOT EXISTS
(SELECT 1
FROM t t2
WHERE t2.colc = t.colc
AND t2.cold = t.cold
GROUP BY colc, cold
HAVING COUNT(*) > 1)
Check out the test here: http://rextester.com/BSVW57900

compare values in the same coloumn in mysql

i have table like that in mysql:
from value to
1 45 2
3 20 4
2 45 1
4 20 3
I want to check values 1 to 2 and 2 to 1 has the same values .
can you give me some example not exact query?
Thanks for help.
You can do this with exists. This will return all the instances where the values are not the same:
select t.*
from table t
where not exists (select 1
from table t2
where t2.from = t.to and
t2.to = t.from and
t2.value = t.value
);
One way is to group by the value. Then you can count if the from and to columns have the right values. If the count is greater than zero for both conditions then you have met your requirement.
Hover over to see the query
select value
from your_table
group by value
having sum(from = 1 and to = 2) = 1
and sum(from = 2 and to = 1) = 1
Something like this will return a row where at least one corresponding inverse row does not have a "matching" value:
SELECT a.from, a.to, a.value, b.value
FROM mytable a
JOIN mytable b
ON b.from = a.to
AND b.to = a.from
WHERE a.from < a.to
AND NOT a.value <=> b.value
(NOTE: this query doesn't identify rows that do not have an inverse row, it only identifies rows where an inverse row exists in the table, but that inverse row has a different value.)