How to Add Serial No in Select Statement in Mysql Join - mysql

There is two table in database.
== tblOrder ==
OrderId
Customer
== tblOrderItem ==
OrderItemId
OrderId
ItemId
Qty
Price
My Query :-
SELECT o.OrderId,o.Customer,oi.ItemId,oi.Qty,oi.Price
FROM tblorder o
JOIN tblorderitem oi ON oi.OrderId=o.OrderId
Result :-
+---------+----------+--------+-----+-------+
| OrderId | Customer | ItemId | Qty | Price |
+---------+----------+--------+-----+-------+
| 1001 | john day | 501 | 1 | 10 |
| 1001 | john day | 502 | 2 | 9 |
| 1002 | amy gill | 201 | 5 | 2 |
| 1003 | hardcaur | 501 | 1 | 10 |
| 1003 | hardcaur | 509 | 2 | 5 |
| 1003 | hardcaur | 201 | 2 | 2 |
+---------+----------+--------+-----+-------+
I want to generate SNO and SNOI(Temp Serial No) in select statement so that result will be like this :-
+------+---------+----------+------+--------+-----+-------+
| SNO | OrderId | Customer | SNOI | ItemId | Qty | Price |
+------+---------+----------+------+--------+-----+-------+
| 1 | 1001 | john day | 1 | 501 | 1 | 10 |
| 1 | 1001 | john day | 2 | 502 | 2 | 9 |
| 2 | 1002 | amy gill | 1 | 201 | 5 | 2 |
| 3 | 1003 | hardcaur | 1 | 501 | 1 | 10 |
| 3 | 1003 | hardcaur | 2 | 509 | 2 | 5 |
| 3 | 1003 | hardcaur | 3 | 201 | 2 | 2 |
What will be my query?

You can use variables.
set #ord ='';
set #val1 =1;
set #val2 =0;
select SR_No_1, OrderId, Customer, SR_No_2, ItemId, Qty, Price
from
(
SELECT t.*,
#val1 := if(#ord=OrderId, #val1+1, 1) as SR_No_2,
#val2 := if(#ord=OrderId,#val2, #val2+1) as SR_No_1,
#ord := OrderId
FROM table1 t
) t
ORDER BY orderId asc;
Result:
+---------+---------+----------+---------+--------+-----+-------+
| SR_No_1 | OrderId | Customer | SR_No_2 | ItemId | Qty | Price |
+---------+---------+----------+---------+--------+-----+-------+
| 1 | 1001 | john day | 1 | 501 | 1 | 10 |
| 1 | 1001 | john day | 2 | 502 | 2 | 9 |
| 2 | 1002 | amy gill | 1 | 201 | 5 | 2 |
| 3 | 1003 | hardcaur | 1 | 501 | 1 | 10 |
| 3 | 1003 | hardcaur | 2 | 509 | 2 | 5 |
| 3 | 1003 | hardcaur | 3 | 201 | 2 | 2 |
+---------+---------+----------+---------+--------+-----+-------+
DEMO
P.S. Kindly note that for demonstration purpose i have inserted data to one table. you can modify the query by introducing the join between 2 tables

Related

MySQL select users who was in range of dates

Hello :) I need to create sql which will calculate advances for user but only for that one who was in work. Tables looks like:
users:
| id | firstName | lastName |
| -- | --------- | -------- |
| 1 | John 1 | Test 1 |
| 2 | John 2 | Test 2 |
| 3 | John 3 | Test 3 |
| 4 | John 4 | Test 4 |
users_advances:
| id | user_id | amount | d_add | status_id |
| -- | ------- | ------ | ---------- | --------- |
| 1 | 1 | 100 | 2022-07-09 | 1 |
| 2 | 1 | 50 | 2022-07-10 | 2 |
| 3 | 2 | 100 | 2022-07-03 | 1 |
| 4 | 2 | 50 | 2022-07-05 | 2 |
| 5 | 2 | 100 | 2022-03-09 | 1 |
| 6 | 1 | 50 | 2022-07-02 | 2 |
users_arrivals
| id | user_id | start_date | end_date |
| -- | ------- | ---------- | ---------- |
| 1 | 1 | 2022-09-01 | 2022-09-30 |
| 2 | 2 | 2022-09-22 | 2022-09-25 |
| 3 | 3 | 2022-09-19 | 2022-09-25 |
I created SQL
SELECT u.id AS user_id, CONCAT(u.firstName, SPACE(1), u.lastName) AS fullName, IFNULL(SUM(uz.amount), 0) AS suma
FROM users u
LEFT JOIN users_advances uz ON uz.user_id = u.id AND (uz.d_add BETWEEN '2022-09-19' AND '2022-09-25') AND ((uz.status_id = 1) OR (uz.status_id = 2))
LEFT JOIN users_arrivals po ON po.user_id = u.id
WHERE po.start_date <= '2022-09-19' AND po.end_date >= '2022-09-24'
GROUP BY u.id
but it doesnt return me user 2 who had start_date at 2022-09-22.

Is there a mySQL procedure that can merge duplicate rows of data into one, then allow me to manipulate that data as if it were one row?

I'm trying to come up with a stored procedure that takes multiple rows that are exactly identical, and combines them into one row while summing one column, which can then be run through more stored procedures based on the sum of that one column.
I've tried a GROUP BY statement, but that doesn't actually group the rows together, because if I run the table through another procedure it performs actions as if each row were not combined. Performing a SELECT * FROM mytable query shows that each row was not actually combined into one.
Is there any way to permanently combine multiple rows into one singular row?
To start, I've got a table like this:
+-------+-----+--------+---------+------+-----+-----------+
| RowID | pID | Name | Date | Code | QTY | Purchased |
+-------+-----+--------+---------+------+-----+-----------+
| 1 | 1 | bob | 9/29/20 | 123 | 1 | |
| 2 | 1 | bob | 8/10/20 | 456 | 1 | |
| 3 | 2 | rob | 9/15/20 | 123 | 1 | |
| 4 | 2 | rob | 9/15/20 | 123 | 1 | |
| 5 | 2 | rob | 9/15/20 | 123 | 1 | |
| 6 | 2 | rob | 9/15/20 | 123 | 1 | |
| 7 | 2 | rob | 9/15/20 | 123 | 1 | |
| 8 | 3 | john | 7/12/20 | 987 | 1 | |
| 9 | 3 | john | 7/12/20 | 987 | 1 | |
| 10 | 4 | george | 9/12/20 | 684 | 1 | |
| 11 | 5 | paul | 2/2/20 | 454 | 1 | |
| 12 | 6 | amy | 1/12/20 | 252 | 1 | |
| 13 | 7 | susan | 5/30/20 | 131 | 1 | |
| 14 | 7 | susan | 6/6/20 | 252 | 1 | |
| 15 | 7 | susan | 5/30/20 | 131 | 1 | |
+-------+-----+--------+---------+------+-----+-----------+
By the end, i'd like to have a table like this:
+-------+-----+--------+---------+------+-----+-----------+
| RowID | pID | Name | Date | Code | QTY | Purchased |
+-------+-----+--------+---------+------+-----+-----------+
| 1 | 1 | bob | 9/29/20 | 123 | 1 | |
| 2 | 1 | bob | 8/10/20 | 456 | 1 | |
| 3 | 2 | rob | 9/15/20 | 123 | 5 | |
| 4 | 3 | john | 7/12/20 | 987 | 2 | |
| 5 | 4 | george | 9/12/20 | 684 | 1 | |
| 6 | 5 | paul | 2/2/20 | 454 | 1 | |
| 7 | 6 | amy | 1/12/20 | 252 | 1 | |
| 8 | 7 | susan | 5/30/20 | 131 | 2 | |
| 9 | 7 | susan | 6/6/20 | 252 | 1 | |
+-------+-----+--------+---------+------+-----+-----------+
Where exactly identical rows are combined into one row, and the QTY field is summed, that I can then add purchases to, or make deductions from the quantity as a total. Using GROUP BY statements can achieve this, but when I go to alter the quantity or add purchases to each person, it treats it like the first table, as if nothing was actually grouped.
So you have this table:
| RowID | pID | Name | Date | Code | QTY | Purchased |
+-------+-----+--------+---------+------+-----+-----------+
| 1 | 1 | bob | 9/29/20 | 123 | 1 | |
| 2 | 1 | bob | 8/10/20 | 456 | 1 | |
| 3 | 2 | rob | 9/15/20 | 123 | 1 | |
| 4 | 2 | rob | 9/15/20 | 123 | 1 | |
| 5 | 2 | rob | 9/15/20 | 123 | 1 | |
| 6 | 2 | rob | 9/15/20 | 123 | 1 | |
| 7 | 2 | rob | 9/15/20 | 123 | 1 | |
| 8 | 3 | john | 7/12/20 | 987 | 1 | |
| 9 | 3 | john | 7/12/20 | 987 | 1 | |
| 10 | 4 | george | 9/12/20 | 684 | 1 | |
| 11 | 5 | paul | 2/2/20 | 454 | 1 | |
| 12 | 6 | amy | 1/12/20 | 252 | 1 | |
| 13 | 7 | susan | 5/30/20 | 131 | 1 | |
| 14 | 7 | susan | 6/6/20 | 252 | 1 | |
| 15 | 7 | susan | 5/30/20 | 131 | 1 | |
The best way, as has been suggested, is to create a new table with the content of your query, then to rename the old table, and the new table to the original table's name, to check if everything is all right, and to drop the original table if yes.
CREATE TABLE indata_new AS
WITH grp AS (
SELECT
MIN(rowid) AS orowid
, pid
, name
, MAX(date) AS date
, code
, SUM(qty) AS qty
FROM indata
GROUP BY
pid
, name
, code
)
SELECT
ROW_NUMBER() OVER(ORDER BY orowid ASC) AS rowid
, *
FROM grp;
ALTER TABLE indata RENAME TO indata_old;
ALTER TABLE indata_new RENAME TO indata;
-- if "indata" now contains the data you want ...
SELECT * FROM indata;
-- out rowid | orowid | pid | name | date | code | qty
-- out -------+--------+-----+--------+------------+------+-----
-- out 1 | 1 | 1 | bob | 2020-09-29 | 123 | 1
-- out 2 | 2 | 1 | bob | 2020-08-10 | 456 | 1
-- out 3 | 3 | 2 | rob | 2020-09-15 | 123 | 5
-- out 4 | 8 | 3 | john | 2020-07-12 | 987 | 2
-- out 5 | 10 | 4 | george | 2020-09-12 | 684 | 1
-- out 6 | 11 | 5 | paul | 2020-02-02 | 454 | 1
-- out 7 | 12 | 6 | amy | 2020-01-12 | 252 | 1
-- out 8 | 13 | 7 | susan | 2020-05-30 | 131 | 2
-- out 9 | 14 | 7 | susan | 2020-06-06 | 252 | 1
-- you can ...
DROP TABLE indata_old;

Mysql Row To Column Select Specific Data

I have column user and rating.
SELECT rating.idUser, user.nmUser, rating.idBengkel, rating.nilai FROM `rating`
JOIN user on rating.idUser = user.idUser
WHERE rating.idBengkel=1 or rating.idBengkel=2
Result :
+--------+---------------------------+-----------+-------+
| idUser | nmUser | idBengkel | nilai |
+--------+---------------------------+-----------+-------+
| 10 | Hudson mas77 | 1 | 5 |
| 11 | Vina Nurfadzilah | 1 | 5 |
| 12 | Angelica Amartya | 1 | 5 |
| 15 | Syahrul K | 1 | 4 |
| 27 | Ashar Murdihastomo | 1 | 5 |
| 28 | Eril Obeit Choiri | 1 | 2 |
| 29 | Ariyadi | 1 | 3 |
| 30 | Robertus Dwian Augusta | 1 | 4 |
| 31 | Irfan Setiaji | 1 | 4 |
| 33 | Baby Ayuna | 1 | 5 |
| 9 | Nur k hamid | 2 | 5 |
| 10 | Hudson mas77 | 2 | 5 |
| 13 | Yuana Putra | 2 | 4 |
| 14 | Nanda Aulia Irza Ramadhan | 2 | 4 |
| 26 | taufiq rahman | 2 | 5 |
| 27 | Ashar Murdihastomo | 2 | 5 |
| 28 | Eril Obeit Choiri | 2 | 5 |
| 30 | Robertus Dwian Augusta | 2 | 4 |
| 44 | halim budiono | 2 | 1 |
+--------+---------------------------+-----------+-------+
When i try to get similar records using this query
SELECT rating.idUser, user.nmUser FROM rating
JOIN user
ON rating.idUser = user.idUser
WHERE rating.idBengkel = 1 and rating.idUser
IN (SELECT rating.idUser from rating WHERE rating.idBengkel = 2)
ORDER by idUser
Result :
+-----------+------------------------+
| idUser | nmUser |
+-----------+------------------------+
| 10 | Hudson mas77 |
| 27 | Ashar Murdihastomo |
| 28 | Eril Obeit Choiri |
| 30 | Robertus Dwian Augusta |
+-----------+------------------------+
The result work fine, but I want show column 'nilai' as ItemX and ItemY. Those are user similar data. In this case I have 4 similar user who rate on idBengkel=1 and idBengkel=2 as the results above. I want it like the table below.
+--------+------------------------+-------+-------+
| idUser | nmUser | ItemX | ItemY |
+--------+------------------------+-------+-------+
| 10 | Hudson mas77 | 5 | 5 |
| 27 | Ashar Murdihastomo | 5 | 5 |
| 28 | Eril Obeit Choiri | 2 | 5 |
| 30 | Robertus Dwian Augusta | 4 | 4 |
+--------+------------------------+-------+-------+
I need solution for this and i was trying with this solution in https://stackoverflow.com/a/7976379/12396302 but it resulting more than one row. Please help me, I cant implement that query's solution. Regards!
I think you need below query -
SELECT rating.idUser,
user.nmUser,
MAX(CASE WHEN rating.idBengkel = 1 THEN rating.nilai END) ItemX,
MAX(CASE WHEN rating.idBengkel = 2 THEN rating.nilai END) ItemY,
FROM `rating`
JOIN user on rating.idUser = user.idUser
WHERE rating.idBengkel IN (1, 2)
GROUP BY rating.idUser,
user.nmUser

How to subtract the sum of value using left join?

I have two tables orders and customers:
select * from orders;
+------+---------------------+-------------+--------+
| oid | date | customer_id | amount |
+------+---------------------+-------------+--------+
| 102 | 2009-10-08 00:00:00 | 4 | 300 |
| 100 | 2009-10-08 00:00:00 | 3 | 15000 |
| 101 | 2008-10-08 00:00:00 | 2 | 1300 |
| 105 | 2010-10-08 00:00:00 | 1 | 400 |
| 106 | 2014-12-23 00:00:00 | 3 | 300 |
+------+---------------------+-------------+--------+
select * from customers;
+------+--------+------+-----------+----------+
| id | name | age | address | salary |
+------+--------+------+-----------+----------+
| 1 | ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | khilan | 25 | delhi | 1500.00 |
| 3 | muffy | 22 | bhopal | 8500.00 |
| 4 | suresh | 48 | mumbai | 24000.00 |
| 1 | ramesh | 32 | Ahmedabad | 300.00 |
| 5 | akil | 21 | madurai | 1000.00 |
| 6 | rajesh | 22 | delhi | 5000.00 |
+------+--------+------+-----------+----------+
What I'm trying to do is to do SUM(salary) from customers and subtract it with the SUM(amount) from orders table. I have tried with this query:
SELECT id ,NAME,SUM(salary),SUM(amount),SUM(salary)-SUM(amount)
FROM customers a LEFT JOIN orders b ON a.id=b.customer_id
GROUP BY NAME;
This will return the following result, which some of them return incorrect value:
+------+--------+-------------+-------------+-------------------------+
| id | name | SUM(salary) | SUM(amount) | SUM(salary)-SUM(amount) |
+------+--------+-------------+-------------+-------------------------+
| 5 | akil | 1000.00 | NULL | NULL |
| 2 | khilan | 1500.00 | 1300 | 200.00 |
| 3 | muffy | 17000.00 | 15300 | 1700.00 |
| 6 | rajesh | 5000.00 | NULL | NULL |
| 1 | ramesh | 2300.00 | 800 | 1500.00 |
| 4 | suresh | 24000.00 | 300 | 23700.00 |
+------+--------+-------------+-------------+-------------------------+
My expected output is as following:
+------+--------+-------------+-------------+-------------------------+
| id | name | SUM(salary) | SUM(amount) | SUM(salary)-SUM(amount) |
+------+--------+-------------+-------------+-------------------------+
| 5 | akil | 1000.00 | NULL | 1000 |
| 2 | khilan | 1500.00 | 1300 | 200.00 |
| 3 | muffy | 8500 | 15300 | -6800 |
| 6 | rajesh | 5000.00 | NULL | 5000 |
| 1 | ramesh | 2300.00 | 400 | 1900.00 |
| 4 | suresh | 24000.00 | 300 | 23700.00 |
+------+--------+-------------+-------------+-------------------------+
One way is to make calculation on orders into sub-query.
To cater for NULL value, you can use IFNULL(value,0).
SELECT id,NAME,SUM(salary),amt,SUM(salary)-IFNULL(amt,0)
FROM customers a LEFT JOIN
(SELECT customer_id, SUM(amount) amt FROM orders GROUP BY customer_id) b
ON a.id=b.customer_id
GROUP BY NAME;

How can I select a column to sum total price from earlier date

+--------+---------+-------+--------+
| billID | orderId | price | date |
+--------+---------+-------+--------+
| 1 | 1 | 100 | 1.3.12 |
| 2 | 1 | 230 | 1.4.12 |
| 3 | 1 | 300 | 1.5.12 |
| 4 | 2 | 1000 | 1.3.12 |
| 5 | 2 | 160 | 1.4.12 |
| 6 | 3 | 400 | 1.3.12 |
+--------+---------+-------+--------+
I want to create view that have column that sum all price have same orderID but with date earlier than rows date. Like this:
+--------+---------+-------+--------+--------------+
| billID | orderId | price | date | add-on price |
+--------+---------+-------+--------+--------------+
| | | | | |
| 1 | 1 | 100 | 1.3.12 | 100 |
| 2 | 1 | 230 | 1.4.12 | 330 |
| 3 | 1 | 300 | 1.5.12 | 630 |
| 4 | 2 | 1000 | 1.3.12 | 1000 |
| 5 | 2 | 160 | 1.4.12 | 1160 |
| 6 | 3 | 400 | 1.3.12 | 400 |
+--------+---------+-------+--------+--------------+
You can user a correlated subquery for this:
select t.*,
(select sum(t2.price)
from table t2
where t2.orderId = t.orderId and t2.date <= t.date
) as CumulativePrice
from table t;