Mysql divide multiple column with 2 statement - mysql

I would like to divide multiple column with 2 statements as the following:
TBL1
NAME VAL1 VAL2 VAL3
A 2 3 3
TBL2
NAME VAL1 VAL2 VAL3
B 2 3 3
ERROR SCRIPT
select (select * from tbl1)/(select * from TBL2) as result
Result that i need as the following:
VAL1 VAL2 VAL3
2/2 3/3 3/3

There should be a ON clause but not sure what it should be
SELECT t1.VAL1/t2.VAL1, t1.VAL2/t2.VAL2, t1.VAL3/t2.VAL3,
FROM TBL1 t1, TBL2 t2

The best thing that I can come up with is
SET #COUNTER1 = 0;
SET #COUNTER2 = 0;
SELECT T1.VAL1 / T2.VAL1,
T1.VAL2 / T2.VAL2,
T1.VAL3 / T2.VAL3
FROM (SELECT *, (#COUNTER1 := #COUNTER1 + 1) AS id FROM TBL1) AS T1
INNER JOIN (SELECT *, (#COUNTER2 := #COUNTER2 + 1) AS id FROM TBL2) AS T2
ON T1.id = T2.id

Select Tbl1.Val1 / Tbl2.Val1 As Val1
, Tbl1.Val2 / Tbl2.Val2 As Val2
, Tbl1.Val3 / Tbl2.Val3 As Val3
From Tbl1
Cross Join Tbl2
Of course, this probaly isn't what you want. Firstly, there is nothing that correlates the rows in Table 1 with the rows in Table 2. I.e., if both tables have three rows each, the result will have nine rows. In short, you will get a Cartesian product between the two tables. Second, there is no logic to deal with dividing by zero errors. Should those values simply be set to zero? Should they be null?
MySQL Join Syntax. (Yes MySQL supports the ISO/ANSI standard Cross Join syntax).
SQL Fiddle version
Edit
If what are trying to do is to concatenate the values into a string expression of #/#, then you need to use the Concat function:
Select Concat(Tbl1.Val1,'/',Tbl2.Val1) As Val1
, Concat(Tbl1.Val2,'/',Tbl2.Val2) As Val2
, Concat(Tbl1.Val3,'/',Tbl2.Val3) As Val3
From Tbl1
Cross Join Tbl2
SQL Fiddle version.

Related

mysql update subquery set

I couldn't find and couldn't produce a solution to this problem with SQL Mysql.
I want to update two columns of a table, and the origin of these values ​​are from another table, having to come randomly.
Here's a tentative example:
update table1 a1,
(select col1, col2
from table2
ORDER BY RAND() limit 1) a2
set a1.col1 = a2.col1, a1.col2 = a2.col2
where a1.col3 is not null;
From this form, the same value from table2 is always coming.
table1 | table2
id col1 col2 | id col1 col2
1 aaa bbb | 1 xxx yyy
2 ccc ddd | 2 www ttt
| 3 uuu vvv
I want the values ​​(col1, col2) from table 2 to be defined in table1 randomly (col1 and col2).
Without Limit 1, it is also being updated with the same record. As if there were 1 record in table2.
That is, for each line of the update, a subquery is made in the other table bringing a record randomly.
You can use join and row_number(), but multiple times:
update table1 t1 join
(select *, row_number() over (order by rand()) as seqnum
from table1 t1
) tt1
on tt1.id = t1.id join
(select *, row_number() over (order by rand()) as seqnum
from table2 t2
) t2
on t2.seqnum = t1.seqnum
set t1.col1 = t2.col1,
t1.col2 = t2.col2;
This adds a sequence number defined randomly to the two tables and joins on that for the matching. The extra join is to implement the update.

GROUP BY another table that have been grouped with two sub query

I have table like this
Table1
ID | Val | Val2 |
606541 |3175031503131004|3175032612900004|
606542 |3175031503131004|3175032612900004|
677315 |3175031503131004|3175032612980004|
222222 |1111111111111111|8888888888888888|
231233 |1111111111111111|3175032612900004|
111111 |9999992222211111|1111111111111111|
57 |3173012102121018|3173015101870020|
59 |3173012102121018|3173021107460002|
2 |900 |7000 |
4 |900 |7001 |
I have two condition with column Val and Val2. Show the result if the Val:
Val column has at least two or more duplicate values AND
Val2 column has no duplicate value (unique)
For example :
Sample 1
ID | Val | Val2 |
606541 |3175031503131004|3175032612900004|
606542 |3175031503131004|3175032612900004|
677315 |3175031503131004|3175032612980004|
False, because even the Val column
had two or more duplicate but the Val2
had dulicate value (ID 606541 and 606542)
Sample Expected 1 Result
No records
Sample 2
ID | Val | Val2 |
222222 |1111111111111111|8888888888888888|
231233 |1111111111111111|3175032612900004|
111111 |9999992222211111|1111111111111111|
True, Because the condition is match,
Val column had duplicate value AND Val2 had unique values
Sample 2 Expected Result
ID | Val | Val2 |
222222 |1111111111111111|8888888888888888|
231233 |1111111111111111|3175032612900004|
Sample 3
ID | Val | Val2 |
606541 |3175031503131004|3175032612900004|
606542 |3175031503131004|3175032612900004|
677315 |3175031503131004|3175032612980004|
222222 |1111111111111111|8888888888888888|
231233 |1111111111111111|3175032612900004|
111111 |9999992222211111|1111111111111111|
Note : This is false condition, Because even the value for id 606541, 606542, and
677315 in column Val had duplicate value at least
two or more but the value in column Val2 had no unique value (it could be true condition if id 606541,
606542, and 677315 had 3 different value on Val2).
NOte 2 : for Id 222222 and 231233 that had duplicate value, this is still false, because the column
Val2 with ID 231233 had the same value with ID 606542 and 606541 (3175032612900004), so it didnt match
the second condition which only have no duplicate value
Sample 3 Expected Result
No records
Now back to Table1 in the earlier, i tried to show result from the two condition with this query
SELECT
tb.* FROM table1 tb
WHERE
tb.Val2 IN (
SELECT ta.Val2
FROM (
SELECT
t.*
FROM
table1 t
WHERE
t.Val IN (
SELECT Val FROM table1
GROUP BY Val
HAVING count( Val ) > 1 )
) ta
GROUP BY
ta.Val2
HAVING
count( ta.Val2 ) = 1
)
The result
ID Val Val2
677315 3175031503131004 3175032612980004
222222 1111111111111111 8888888888888888
57 3173012102121018 3173015101870020
59 3173012102121018 3173021107460002
2 900 7000
4 900 7001
While i expect the result was like this:
ID Val Val2
57 3173012102121018 3173015101870020
59 3173012102121018 3173021107460002
2 900 7000
4 900 7001
Is there something wrong with my query ?
Here is my DB Fiddle.
Excuse for any mistakes as this would be my first answer in this forum.
Could you also try with below, i agree to the answer with window function though.
SELECT t.*
FROM table1 t
WHERE t.val IN (SELECT val
FROM table1
GROUP BY val
HAVING COUNT(val) > 1
AND COUNT(val) = COUNT(DISTINCT val2)
)
AND t.val NOT IN (SELECT t.val
FROM table1 t
WHERE EXISTS (SELECT 1
FROM table1 tai
WHERE tai.id != t.id
AND tai.val2 = t.val2));
/*
first part of where clause makes sure we have distinct values in column val2 for repeated value in column val
second part of where clause with not in tells us there is no value shares across different ids with respect to value in column val2
*/
--reverse order query ( not sure gives the expected result)
SELECT t.*
FROM table2 t
WHERE t.val IN (SELECT val FROM table2 GROUP BY val HAVING COUNT(val) = 1)
AND t.val2 IN (SELECT t.val2
FROM table2 ta
WHERE EXISTS (SELECT 1
FROM table2 tai
WHERE tai.id != ta.id
AND tai.val = ta.val));
You have to use Group By to find val & val2 with duplicate values and need to use Inner Join and Left Join in order to include/eliminate records as given conditions (oppose to IN, NOT IN etc. clauses that might cause performance issues in case you're dealing with large data).
Please find the query below:
select t1.*from table1 t1 left join
(select val from table1
where val2 in (select val2 from table1 group by val2 having count(id) > 1)
) t2
on t1.val = t2.val
inner join
(select val from table1 group by val having count(id) >1) t3
on t1.val = t3.val
where t2.val is null
Query for Reverse Condition:
select t1.*from table1 t1 inner join
(select val from table1 group by val having count(id) = 1)
t2
on t1.val = t2.val
inner join
(select val2 from table1 group by val2 having count(id) >1) t3
on t1.val2 = t3.val2
Please find fiddle for both queries here.
Can you try this and let me know the results? SQL fiddle
SELECT t1.id, t1.val, t1.val2 FROM table1 t1
JOIN (
select val from
(select id, val, val2 from table1 group by val2 having count(1) = 1) a
group by a.val having count(1) > 1
)t2 on t1.val = t2.val;
you can use group by :
select * from (select * from #table1 where Val2 in (select Val2 val from #table1 group by Val2 having COUNT(*) =1 )) select1
where select1.val in (select Val val from #table1 group by Val having COUNT(*) >1)
or you can use RANK :
select * from ( SELECT
i.id,
i.Val val,
RANK() OVER (PARTITION BY i.val ORDER BY i.id DESC) AS Rank1,
RANK() OVER (PARTITION BY i.val2 ORDER BY i.id DESC) AS Rank2
FROM #table1 AS i
) select1 where select1.Rank1 >1 or select1.Rank2 =2
You don't need group by or having. Sub-selects will do the job just fine.
SELECT * FROM MyTable a
WHERE (SELECT Count(*) FROM MyTable b WHERE a.val = b.val) >= 2
AND (SELECT Count(*) FROM MyTable c WHERE a.val2 = c.val2) = 1;
This looks at the table as if it was 3 identical tables, but it's just one. The first sub select
(SELECT Count(*) FROM MyTable b WHERE a.val = b.val)
returns a number containing how many occurrences of "Val" are in the table; if there are at least 2 we're good to go. The second sub select
(SELECT Count(*) FROM MyTable c WHERE a.val2 = c.val2)
returns a number containing how many occurrences of "Val2" are in the table; if it's 1 and the first sub select returns at least 2 then we print the record.
If you want a solution, i think this will help.
I got the
val2s which has no duplicates
vals which has more than 1 duplicates
and join
Select t.* from
table1 t
inner join
(Select val2 from table1 group by val2 having count(*) = 1) tv2 on t.val2 = tv2.val2
inner join
(Select val from table1 group by val having count(*) > 1) tv on t.val = tv.val;
You can do it with EXISTS and NOT EXISTS.
If you want only the column Val:
select t1.val from table1 t1
where not exists (
select 1 from table1
where val = t1.val and val2 in (select val2 from table1 group by val2 having count(*) > 1)
)
group by t1.val
having count(t1.val) > 1
If you want full rows:
select t1.* from table1 t1
where exists (select 1 from table1 where id <> t1.id and val = t1.val)
and not exists (
select 1 from table1
where val = t1.val and val2 in (select val2 from table1 group by val2 having count(*) > 1)
)
And one solution with window functions for MySql 8.0+:
select t.id, t.val, t.val2
from (
select *, max(counter2) over (partition by val) countermax
from (
select *,
count(*) over (partition by val) counter,
count(*) over (partition by val2) counter2
from table1
) t
) t
where t.counter > 1 and t.countermax = 1
See the demo.
Common Table Expressions may help readability and perhaps performance as well.
with dup as (select val, count(*) -- two or more of val
from table1
group by val
having count(*)>1)
select tb1.*
from table1 tb1
inner join dup
on dup.val = tb1.val
where not exists (select val2, count(*) -- Not exists is generally fast
from table1
where val = tb1.val
group by 1
having count(*) > 1)
Fiddle
I'm going through your dataset at the moment, and I feel like your final result is accurate when you compare the results to your original dataset. Your criteria used are:
Val is duplicated at least once
Val2 is unique
9999992222211111 is the only unique value in the Val list, so that's the only value I don't expect to see in the final result. For Val2, the only duplicated value is 3175032612900004, so I don't expect to see in the final result.
What it sounds like you're trying to do is to apply the original conditions to your final result table (which is different from your original data table). If that's what you're after, you can go through the same process applied to the original table to your new table, in which you'll get the exact result you want.
I've taken that and included all of this in my fiddle below. You'll see two output queries, one with the result you're seeing, and one with the result you want. Let me know if this answers your question! =)
Here's my fiddle: fiddle
The answer to your query
Is there something wrong with my query ?
is in your Note 2 of Sample 3
NOte 2 : for Id 222222 and 231233 that had duplicate value, this is still false, because the column
Val2 with ID 231233 had the same value with ID 606542 and 606541 (3175032612900004), so it didnt match
the second condition which only have no duplicate value
You are not eliminating the records where Val2 is duplicate with another record outside the set. So, all you need to do in your query is to add the below condition
AND tb.Val NOT IN (SELECT t.Val
FROM table1 t
WHERE t.Val2 IN (SELECT Val2 FROM table1 GROUP BY Val2 HAVING count( Val2 ) > 1 ))
I have added this condition to your query and see the expected results. See fiddle below
My Fiddle
The answer given by #Govind feels like a better re-write of your requirements. It is checking for the duplicates of Val column only when there are no duplicates in Val2 column. Very neat and concise query.
Answer by Govind
Something like this?
SELECT *
FROM table1
WHERE val IN
(SELECT val
FROM table1
GROUP BY val
HAVING COUNT(*) > 1 AND COUNT(DISTINCT val2) = COUNT(*))
AND val NOT IN (SELECT t.val
FROM table1 t
INNER JOIN (SELECT val2
FROM table1
GROUP BY val2
HAVING COUNT(*) > 1) x
ON x.val2 = t.val2);
`select val, count(*) from table1 group by val having count(*)>=2;`
`val count(*)`
`1111111111111111 2`
`3173012102121018 2`
`3175031503131004 3`
`900 2`
Val column has at least two or more duplicate values - TRUE
select val2, count(*) from table1 group by val2 having count(*)>1;
`val2 count(*)`
`3175032612900004 3`
Val2 column has no duplicate value (unique) - FALSE
So ideally you should get no records found right?

Is there a way I can skip by value in mysql?

I'm try to skip values continuously in my MySQL table, for example:
I have a table here
time value
t1 val1
t2 val2
t3 val3
t4 val4
t5 val5
And the result that i need is
time value
t1 val1
t3 val3
t5 val5
Hopefully you guys understand my problem
Similarly I need to skip by 2 values,3,4 and 5.
Assuming that the order is defined by time, in MySQL 8+ you can use row_number() to assign a number to each row ordered by time and then pick only the rows with an odd number using the modulo operator %.
SELECT x.time,
x.value
FROM (SELECT t.time,
t.value,
row_number() OVER (ORDER BY t.time) rn) x
WHERE rn % 2 = 1;
You can use IN statement
SELECT * FROM TABLE_NAME WHERE NOT IN(values);
values=(2,4,....);
You will get results , and in values you can pass array as you don't want value

MySQL if / else or select if(contiton,'true','false'); - Syntax-problems

When I use
select if (1=1,'true','false');
then everything is ok and I receive 'true' but if I try
select if (1=1,(select * from table1), (select * from table2));`
I receive syntax error in mysql!
With
if condition then <SQL-Expression1> else <SQL-Expression2> end if;
I have the same problem, when the SQL-Expression is complex like
select * from table1!
If I use a complex SQL-Expression like
select * from table1
or
insert into table1 (select field1 from table2 where
field1>(select Max(field) from table1));
then I always receive a syntax error, when such a expression is included in an if/else-Statement!
How can I fit it, that complex sql-Statements can be choosed?
My problem is:
I made 2 tables like
create table1 (x1 int4, x2 int4, x3 int4);
create table2 (x int4);
insert into table1 values(1,2,3);
insert into table1 values(4,0,5);
I wanted to transponse table1 to table2
For example:
The result should in table2 like this
1
2
3
4
5
If I enlarge table 1 with a new line like
insert into table1 values (6,7,8);
then table2 should be changed to
1
2
3
4
5
6
7
8
I tried to make it in this way
select if ((select count(*) from table2)=0,
(insert into table2 (select x1 from table1 where x1>0)),
(insert into table2 (select x1 from table1 where
x1>(select Max(x) from table1))));
The same also with x2 and x3.
but syntax errors occur!
If I use only
insert into table2 (select x1 from table1 where x1>(select Max(x) from table1));
then it works if table1 ist not empty otherwise I had to do
insert into table2 (select x1 from table1 where x1>0);
Subqueries in the SELECT clause may only return single values; i.e. not more than one result, and not more than one column. You can't "trick" a query into returning a varying number of columns.
Also, the if-then form of "if" is reserved for procedural sql; used in stored procedures, triggers, etc...

find the output mysql query

I have a table name T1 having only one Column name Col1 having rows –
Col1
a
b
c
And another table name T2 also having only one Column name Col1 having rows –
Col1
x
y
z
Now I want record like
Col1--Col2
a------x
b------y
c------z
I am using mysql.
Thanks in advance!!
create table T1(col1 varchar(10));
insert T1 values ('a'),('b'),('c');
create table T2(col2 varchar(10));
insert T2 values ('x'),('y'),('z');
select A.col1, B.col2 from
(select #r:=#r+1 rownum, col1 from (select #r:=0) initvar, T1) A,
(select #s:=#s+1 rownum, col2 from (select #s:=0) initvar, T2) B
where A.rownum=B.rownum
Because there is no ORDER BY clause, you are depending on luck and convention for the row numbering to be according to the order inserted. It may not always be the case.
In your example, if you want to join the tables to get row results like this:
Row 1 - A,X
Row 2 - B,Y
Row 3 - C,Z
..then you will have to add a common field that you can JOIN the two tables on.
If you want to be able to return results from both tables like this:
Row 1 - A
Row 2 - B
Row 3 - C
Row 4 - X
Row 5 - Y
Row 6 - Z
.. then you will need to use a UNION:
(SELECT Col1 FROM T1) UNION (SELECT Col1 FROM T2)