How to use union for handling date from two different tables - mysql

I have two tables. First table stk
ITEMID | STOCK
--------------
Test1 | 10
Test2 | 15
Test3 | 12
and second table qty
ITEMID | DOCDATE | QTY
--------------------------
Test1 | 2/28/2017 | 5
Test2 | 2/28/2017 | 8
Test3 | 2/28/2017 | 6
I used this query
select itemid,stock,docdate,qty
from (
select itemid,stock,null docdate,0 qty from stk
union
select itemid,0 stock,docdate,qty from qty
)
group by itemid,stock,docdate,qty
order by 1
Output I get:
ITEMID | STOCK | DOCDATE | QTY
------------------------------
Test1 | 0 |2/28/2017 | 5
Test1 | 10 | | 0
Test2 | 0 |2/28/2017 | 8
Test2 | 15 | | 0
Test3 | 0 |2/28/2017 | 6
Test3 | 12 | | 0
but I want to have this output:
ITEMID | STOCK | DOCDATE | QTY
------------------------------
Test1 | 10 |2/28/2017 | 5
Test2 | 15 |2/28/2017 | 8
Test3 | 12 |2/28/2017 | 6

If you only want to consolidate rows coming from the two different tables then you can use this query:
select itemid, MAX(stock), MAX(docdate), MAX(qty)
from (
select itemid,stock,null docdate,0 qty from stk
union
select itemid,0 stock,docdate,qty from qty
) as t
group by itemid
order by 1
Demo here

If your only goal is to have that output, then you can just do this:
SELECT Q.ItemId, (SELECT S.stock FROM stk S ON S.ItemId = Q.ItemId) AS STOCK, Q.DocDate, Q.Qty FROM qty Q
I am using subqueries to connect the two tables on Id, and then I select the stock from Stk where the ItemId is the same as the ItemId from Qty.

Unions are vertical joins are horizontal. Perhaps something like this is required.
MariaDB [sandbox]> create table stk(ITEMID varchar(10), STOCK int);
Query OK, 0 rows affected (0.20 sec)
MariaDB [sandbox]> insert into stk values
-> ('Test1' , 10),
-> ('Test2' , 15),
-> ('Test3' , 12);
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> drop table if exists qty;
Query OK, 0 rows affected (0.14 sec)
MariaDB [sandbox]> create table qty(ITEMID varchar(10), DOCDATE varchar(10) , QTY int);
Query OK, 0 rows affected (0.20 sec)
MariaDB [sandbox]> insert into qty values
-> ('Test1' , '2/28/2017' , 5),
-> ('Test2' , '2/28/2017' , 8),
-> ('Test3' , '2/28/2017' , 6),
-> ('Test1' , '3/28/2017' , 7),
-> ('Test2' , '3/28/2017' , 7),
-> ('Test3' , '3/28/2017' , 7);
Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select s.itemid,s.stock,
-> q.docdate,sum(q.qty) qty
-> from stk s
-> join qty q on q.itemid = s.itemid
-> group by s.itemid,s.stock,q.docdate
-> order by q.docdate, s.itemid,s.stock
->
-> ;
+--------+-------+-----------+------+
| itemid | stock | docdate | qty |
+--------+-------+-----------+------+
| Test1 | 10 | 2/28/2017 | 5 |
| Test2 | 15 | 2/28/2017 | 8 |
| Test3 | 12 | 2/28/2017 | 6 |
| Test1 | 10 | 3/28/2017 | 7 |
| Test2 | 15 | 3/28/2017 | 7 |
| Test3 | 12 | 3/28/2017 | 7 |
+--------+-------+-----------+------+
6 rows in set (0.00 sec)

Use JOIN to get result:
SELECT ITEMID ,STOCK,DOCDATE,QTY
FROM table1
JOIN table2 ON table1.ITEMID = table2.ITEMID

Related

How to apply case when with if condition in MySql

I have below mentioned two tables:
Table 1
ID Key
TTT-1 atre-0-1
TTT-2 atrt-4-2
TTT-3 attr-1-3
TTT-4 aert-2-5
Table2
Key Red1 Red2
atre-0-1 10 25
atre-0-1 15 07
atre-0-1 16 19
atrt-4-2 11 21
atrt-4-2 07 22
attr-1-3 -4 3
attr-1-3 33 11
attr-1-3 50 45
aert-2-5 -5 2
aert-2-5 -4 1
By utilizing the above tow tables, I want to fetch the minimum value of Red1 and Red2 group by ID with the below mentioned condition.
For any ID if any Red1 and Red2 value is between -5 to 5 than consider the other values which are maximum of five, If there are only one entry available for a ID against which value is between range -5 to 5 than only consider -5 to 5 value for minimum criteria.
Required Output:
ID Number
TTT-1 07
TTT-2 07
TTT-3 11
TTT-4 -5
I have written below mentioned query, but it didn't work properly.
select t1.ID,
case when min(t2.Red1)<min(t2.Red2) then min(t2.Red1) else min(t2.Red2) End as `Number`
from Table1 t1
left join Table2 t2 on t1.key=t2.key
group by t1.ID;
The following query should solve this problem:
SELECT t1.ID,
CASE WHEN min(t2.Red1)<min(t2.Red2) THEN t2.min_red1 ELSE t2.min_red2 END AS
`Number`
FROM Table1 t1
LEFT JOIN
(
SELECT
key,
Red1
Red2
min(Red1) AS min_red1,
min(Red2) AS min_red2
FROM Table2 ) AS t2
ON t1.key=t2.key
GROUP BY t1.ID;
You can use the below SQL, here is the example as per your expectation.
Query:
SELECT
a.ID,
CASE
WHEN
LEAST(MIN(b.red1), MIN(b.red2)) BETWEEN - 5 AND 5
THEN
IFNULL(LEAST(MIN(CASE
WHEN red1 NOT BETWEEN - 5 AND 5 THEN red1
END),
MIN(CASE
WHEN red2 NOT BETWEEN - 5 AND 5 THEN red2
END)),
LEAST(MIN(b.red1), MIN(b.red2)))
ELSE LEAST(MIN(b.red1), MIN(b.red2))
END AS `Number`
FROM
table1 a
JOIN
table2 b ON a.key = b.key
GROUP BY a.ID;
Example:
mysql> create table table1(ID varchar(20),`key` varchar(20));
Query OK, 0 rows affected (0.23 sec)
mysql> insert into table1 values
-> ('TTT-1','atre-0-1'),
-> ('TTT-2','atrt-4-2'),
-> ('TTT-3','attr-1-3'),
-> ('TTT-4','aert-2-5');
Query OK, 4 rows affected (0.27 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql>
mysql> create table table2(`key` varchar(20),red1 int(5),red2 int(5));
Query OK, 0 rows affected (0.30 sec)
mysql> insert into table2 values
-> ('atre-0-1',10,25),
-> ('atre-0-1',15,07),
-> ('atre-0-1',16,19),
-> ('atrt-4-2',11,21),
-> ('atrt-4-2',07,22),
-> ('attr-1-3',-4,3),
-> ('attr-1-3',33,11),
-> ('attr-1-3',50,45),
-> ('aert-2-5',-5,2),
-> ('aert-2-5',-4,1);
Query OK, 10 rows affected (0.29 sec)
Records: 10 Duplicates: 0 Warnings: 0
mysql>
mysql> select * from table1;
+-------+----------+
| ID | key |
+-------+----------+
| TTT-1 | atre-0-1 |
| TTT-2 | atrt-4-2 |
| TTT-3 | attr-1-3 |
| TTT-4 | aert-2-5 |
+-------+----------+
4 rows in set (0.20 sec)
mysql> select * from table2;
+----------+------+------+
| key | red1 | red2 |
+----------+------+------+
| atre-0-1 | 10 | 25 |
| atre-0-1 | 15 | 7 |
| atre-0-1 | 16 | 19 |
| atrt-4-2 | 11 | 21 |
| atrt-4-2 | 7 | 22 |
| attr-1-3 | -4 | 3 |
| attr-1-3 | 33 | 11 |
| attr-1-3 | 50 | 45 |
| aert-2-5 | -5 | 2 |
| aert-2-5 | -4 | 1 |
+----------+------+------+
10 rows in set (0.21 sec)
mysql>
mysql> SELECT
-> a.ID,
-> CASE
-> WHEN
-> LEAST(MIN(b.red1), MIN(b.red2)) BETWEEN - 5 AND 5
-> THEN
-> IFNULL(LEAST(MIN(CASE
-> WHEN red1 NOT BETWEEN - 5 AND 5 THEN red1
-> END),
-> MIN(CASE
-> WHEN red2 NOT BETWEEN - 5 AND 5 THEN red2
-> END)),
-> LEAST(MIN(b.red1), MIN(b.red2)))
-> ELSE LEAST(MIN(b.red1), MIN(b.red2))
-> END AS `Number`
-> FROM
-> table1 a
-> JOIN
-> table2 b ON a.key = b.key
-> GROUP BY a.ID;
+-------+--------+
| ID | Number |
+-------+--------+
| TTT-1 | 7 |
| TTT-2 | 7 |
| TTT-3 | 11 |
| TTT-4 | -5 |
+-------+--------+
4 rows in set (0.28 sec)

update inner select successful but data not update

this is my code
UPDATE `mytable`
SET `income` = (SELECT sum(`row`) FROM (SELECT * FROM `mytable`)AS mmc WHERE `view_date` = '2018-5-21')
WHERE id = 1 AND view_date = '2018-5-21'
I run this code and it successful, but my data was not update.
You can use the below SQL to update your table properly.
SQL:
update mytable m
join (select id,view_date,sum(row) as row from mytable group by id,view_date) t on (m.id = t.id and m.view_date = t.view_date)
set m.income = t.row
where m.id = 1 and m.view_date = '2018-05-23';
Example are below:
mysql> create table mytable(id int,income int, row int, view_date date);
Query OK, 0 rows affected (0.54 sec)
mysql> insert into mytable values(1,null,230,current_date);
Query OK, 1 row affected (0.12 sec)
mysql> insert into mytable values(1,null,450,current_date);
Query OK, 1 row affected (0.05 sec)
mysql> select * from mytable;
+------+--------+------+------------+
| id | income | row | view_date |
+------+--------+------+------------+
| 1 | NULL | 230 | 2018-05-23 |
| 1 | NULL | 450 | 2018-05-23 |
| 2 | NULL | 800 | 2018-05-23 |
+------+--------+------+------------+
3 rows in set (0.00 sec)
mysql> update mytable m
-> join (select id,view_date,sum(row) as row from mytable group by id,view_date) t on (m.id = t.id and m.view_date = t.view_date)
-> set m.income = t.row
-> where m.id = 1 and m.view_date = '2018-05-23';
Query OK, 2 rows affected (0.13 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> select * from mytable;
+------+--------+------+------------+
| id | income | row | view_date |
+------+--------+------+------------+
| 1 | 680 | 230 | 2018-05-23 |
| 1 | 680 | 450 | 2018-05-23 |
| 2 | NULL | 800 | 2018-05-23 |
+------+--------+------+------------+
3 rows in set (0.00 sec)

trigger to update table contribution calculation using mysql

I need to calculate contribution base on project per developer
Contribution table
-------------------------------------------------------------
| id | projected | developer id | total hours | contribution|
-------------------------------------------------------------
| 1 | 1 | 1 | 25 | |
-------------------------------------------------------------
| 2 | 1 | 2 | 75 | |
-------------------------------------------------------------
| 3 | 2 | 1 | 10 | |
-------------------------------------------------------------
need to update same table with trigger after insert and update
expected result
Contribution table
-------------------------------------------------------------
| id | projected | developer id | total hours | contribution|
-------------------------------------------------------------
| 1 | 1 | 1 | 25 | 25% |
------------------------------------------------------------
| 2 | 1 | 2 | 75 | 75% |
-------------------------------------------------------------
| 3 | 2 | 1 | 10 | 100% |
-------------------------------------------------------------
calculation for the getting contribution
project 1 :
total hours = 25 + 75 = 100
contribution per developer = 25/100*100
= 25%
i need a trigger to get this result: but don't know how to get this
This is my trigger not getting error but contribution calculation not correct
CREATE TRIGGER `update_contribution` AFTER INSERT ON `tasks`
FOR EACH ROW BEGIN
IF NOT EXISTS
(SELECT p_id ,d_id
FROM contribution
WHERE
p_id = NEW.p_id
AND
d_id = NEW.d_id)
THEN
SET #old_total_dev_hours = (SELECT SUM(total_hours)
FROM contribution
WHERE p_id = NEW.p_id
GROUP BY p_id);
SET #total_hours1 = (SELECT (total_hours)
FROM contribution
WHERE d_id = NEW.d_id AND p_id = NEW.p_id
);
SET #dev_con = #total_hours1/#old_total_dev_hours*100 ;
SET #total_hours = new.hours + new.overtime;
INSERT INTO contribution
( p_id,
d_id,
hours,
overtime,
total_hours,
contribution
)
VALUES
(NEW.p_id,
NEW.d_id,
NEW.hours,
NEW.overtime,
#total_hours ,
#dev_con
);
ELSE
UPDATE contribution
SET
hours = hours + NEW.hours ,
overtime = overtime + NEW.overtime,
total_hours = hours + overtime,
contribution = #dev_con
WHERE
p_id = NEW.p_id
AND
d_id = NEW.d_id;
END IF;
END
This is my code in this code other calculation are working fine
contribution is not getting correctly!!
Here's an updated trigger that would replace the one from your previous question. It calculates
both values for the total_hours and contribution percentage.
DELIMITER |
CREATE TRIGGER update_hours AFTER INSERT ON tasks
FOR EACH ROW
BEGIN
SET #old_total_dev_hours = (SELECT SUM(hours + overtime)
FROM contribution
WHERE p_id == new.p_id && d_id == new.d_id
GROUP BY p_id,d_id);
SET #old_total_hours = (SELECT SUM(hours + overtime)
FROM contribution
WHERE p_id == new.p_id
GROUP BY p_id);
SET #total_hours = #old_total_dev_hours + new.hours + new.overtime;
SET #contrib_percent = (#old_total_dev_hours / #old_total_hours) * 100;
INSERT INTO contribution
( p_id,
d_id,
hours,
overtime,
total_hours,
contribution )
VALUES
(
NEW.p_id,
NEW.d_id,
NEW.hours,
NEW.overtime,
#total_hours,
#contrib_percent
);
END|
DELIMITER ;
Assuming tasks logs hours worked by developers on projects then 2 things can happen 1) there is no note that a developer has worked on a project in contribution 2) a developer has worked on a project and the hours he has worked need to updated in contribution. Both cases imply that all developer contributions need to be recalculated on each insert to tasks.
For example
drop table if exists t,contribution;
create table t(id int auto_increment primary key, developerid int, projectid int,hrs_normal int, hrs_overtime int);
create table contribution(id int auto_increment primary key, projectid int,
developerid int, hrs int, contribution decimal (6,3) default 0);
drop trigger if exists t;
delimiter $$
create trigger t after insert on t
for each row
begin
declare totalhours int default 0;
set totalhours = (select ifnull(sum(hrs),0) from contribution where projectid = new.projectid);
set totalhours = totalhours + ifnull(new.hrs_normal,0) + ifnull(new.hrs_overtime,0);
if not exists (select 1 from contribution where projectid = new.projectid and developerid = new.developerid) then
insert into contribution(projectid,developerid,hrs)
values
(new.projectid,new.developerid,ifnull(new.hrs_normal,0) + ifnull(new.hrs_overtime,0)
);
else
update contribution
set hrs = hrs + ifnull(new.hrs_normal,0) + ifnull(new.hrs_overtime,0)
where developerid = new.developerid and projectid = new.projectid;
end if;
update contribution
set contribution = (hrs / totalhours) * 100
where projectid = new.projectid;
end $$
delimiter ;
MariaDB [sandbox]> truncate table t;
Query OK, 0 rows affected (0.28 sec)
MariaDB [sandbox]> truncate table contribution;
Query OK, 0 rows affected (0.25 sec)
MariaDB [sandbox]> select * from t;
Empty set (0.00 sec)
MariaDB [sandbox]> select * from contribution;
Empty set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> insert into t (developerid , projectid ,hrs_normal , hrs_overtime )
-> values
-> (1,1,10,0);
Query OK, 1 row affected (0.02 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+----+-------------+-----------+------------+--------------+
| id | developerid | projectid | hrs_normal | hrs_overtime |
+----+-------------+-----------+------------+--------------+
| 1 | 1 | 1 | 10 | 0 |
+----+-------------+-----------+------------+--------------+
1 row in set (0.00 sec)
MariaDB [sandbox]> select * from contribution;
+----+-----------+-------------+------+--------------+
| id | projectid | developerid | hrs | contribution |
+----+-----------+-------------+------+--------------+
| 1 | 1 | 1 | 10 | 100.000 |
+----+-----------+-------------+------+--------------+
1 row in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> insert into t (developerid , projectid ,hrs_normal , hrs_overtime )
-> values
-> (1,1,10,0),(2,1,30,10);
Query OK, 2 rows affected (0.05 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+----+-------------+-----------+------------+--------------+
| id | developerid | projectid | hrs_normal | hrs_overtime |
+----+-------------+-----------+------------+--------------+
| 1 | 1 | 1 | 10 | 0 |
| 2 | 1 | 1 | 10 | 0 |
| 3 | 2 | 1 | 30 | 10 |
+----+-------------+-----------+------------+--------------+
3 rows in set (0.00 sec)
MariaDB [sandbox]> select * from contribution;
+----+-----------+-------------+------+--------------+
| id | projectid | developerid | hrs | contribution |
+----+-----------+-------------+------+--------------+
| 1 | 1 | 1 | 20 | 33.333 |
| 2 | 1 | 2 | 40 | 66.667 |
+----+-----------+-------------+------+--------------+
2 rows in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> insert into t (developerid , projectid ,hrs_normal , hrs_overtime )
-> values
-> (1,1,10,0),(2,2,30,10);
Query OK, 2 rows affected (0.05 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+----+-------------+-----------+------------+--------------+
| id | developerid | projectid | hrs_normal | hrs_overtime |
+----+-------------+-----------+------------+--------------+
| 1 | 1 | 1 | 10 | 0 |
| 2 | 1 | 1 | 10 | 0 |
| 3 | 2 | 1 | 30 | 10 |
| 4 | 1 | 1 | 10 | 0 |
| 5 | 2 | 2 | 30 | 10 |
+----+-------------+-----------+------------+--------------+
5 rows in set (0.00 sec)
MariaDB [sandbox]> select * from contribution;
+----+-----------+-------------+------+--------------+
| id | projectid | developerid | hrs | contribution |
+----+-----------+-------------+------+--------------+
| 1 | 1 | 1 | 30 | 42.857 |
| 2 | 1 | 2 | 40 | 57.143 |
| 3 | 2 | 2 | 40 | 100.000 |
+----+-----------+-------------+------+--------------+
3 rows in set (0.00 sec)
Note if the business rules are that a developers hours can amended in tasks you will also need and update trigger along the same lines.

mysql join extracted number

I have a 'big' table like this
id user type comment
6 1 A id '3' - #8
7 1 A id '3' - #9
8 3 B
9 3 B
I want to extract the numbers after the hash and join it with the id column to have the following (when the number between the single quotes is equal to the user)
id1 id2 user type
6 8 3 B
7 9 3 B
A create a copy of your table, its name is bigtable and insert those values that you gave us:
mysql> create table bigtable (id int, user_id int, type varchar(10), comment varchar(30));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into bigtable values (6,1, 'A', 'id 3 - #8'),(7,1,'A', 'id 3 - #9'),(8,3, 'B','' ),(9,3, 'B','');
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from bigtable;
+------+---------+------+-----------+
| id | user_id | type | comment |
+------+---------+------+-----------+
| 6 | 1 | A | id 3 - #8 |
| 7 | 1 | A | id 3 - #9 |
| 8 | 3 | B | |
| 9 | 3 | B | |
+------+---------+------+-----------+
4 rows in set (0.00 sec)
I did a self join and use the substrn_index function:
mysql> select b1.id,b2.id,b1.user_id,b1.type
from bigtable as b1 join bigtable as b2
on b1.id=SUBSTRING_INDEX(b2.COMMENT,'#',-1);
+------+------+---------+------+
| id | id | user_id | type |
+------+------+---------+------+
| 8 | 6 | 3 | B |
| 9 | 7 | 3 | B |
+------+------+---------+------+
2 rows in set (0.00 sec)
I hope this helped you

Selecting total value, and a subset of it

I have a table with different values for different countries, for example:
id| country | value
===================
1 | Argelia | 8
2 | USA | 10
1 | China | 12
1 | Italy | 13
I am interested in only one country and the total, but I'm having trouble coming up with a single query to do it. The result of this query for id 1 would be:
id| value_in_Italy | total
==========================
1 | 13 | 33
As you can see, I obtained the value for Italy, and the total value. What kind of query would produce rows like the above for a similar table?
Here is the query you need:
select id,SUM(IF(country='Italy',value,0)) italy_value,SUM(value) id_values
from countrydata where id = 1;
Here is your sample data:
drop database if exists luqita;
create database luqita;
use luqita
create table countrydata
(
id int not null,
country varchar(32),
value int not null
);
insert into countrydata values
(1,'Argelia', 8 ),(2,'USA' , 10 ),
(1,'China' , 12 ),(1,'Italy' , 13 );
select * from countrydata;
Here is your sample data loaded:
mysql> drop database if exists luqita;
Query OK, 1 row affected (0.03 sec)
mysql> create database luqita;
Query OK, 1 row affected (0.02 sec)
mysql> use luqita
Database changed
mysql> create table countrydata
-> (
-> id int not null,
-> country varchar(32),
-> value int not null
-> );
Query OK, 0 rows affected (0.12 sec)
mysql> insert into countrydata values
-> (1,'Argelia', 8 ),(2,'USA' , 10 ),
-> (1,'China' , 12 ),(1,'Italy' , 13 );
Query OK, 4 rows affected (0.05 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from countrydata;
+----+---------+-------+
| id | country | value |
+----+---------+-------+
| 1 | Argelia | 8 |
| 2 | USA | 10 |
| 1 | China | 12 |
| 1 | Italy | 13 |
+----+---------+-------+
4 rows in set (0.00 sec)
mysql>
Here is the proposed query executed:
mysql> select id,SUM(IF(country='Italy',value,0)) italy_value,SUM(value) id_values
-> from countrydata where id = 1;
+----+-------------+-----------+
| id | italy_value | id_values |
+----+-------------+-----------+
| 1 | 13 | 33 |
+----+-------------+-----------+
1 row in set (0.00 sec)
mysql>
Now, if you want to run this query against all rows at the same time, try this all-inclusive query:
select
B.id,
SUM(IF(A.country=B.country,B.value,0)) country_value,
SUM(IF(A.id=B.id,A.value,0)) id_values
from
countrydata A,
countrydata B
group by B.country;
Here is that all-inclusive query execute
mysql> select
-> B.id,
-> SUM(IF(A.country=B.country,B.value,0)) country_value,
-> SUM(IF(A.id=B.id,A.value,0)) id_values
-> from
-> countrydata A,
-> countrydata B
-> group by B.country;
+----+---------------+-----------+
| id | country_value | id_values |
+----+---------------+-----------+
| 1 | 8 | 33 |
| 1 | 12 | 33 |
| 1 | 13 | 33 |
| 2 | 10 | 10 |
+----+---------------+-----------+
4 rows in set (0.00 sec)
mysql>
Give it a Try !!!