mysql with join in mysql - mysql

**i have a 3 tables in mysql **
1- Client Table
PK
NUM_CLIENT
NAME_CLIENT
1
ALEX
2
ADAM
2- Invoice Table
FK
NUM_CLIENT_INV
INV_VALUE
1
1000
1
2000
3- Sales returns Table
FK
NUM_CLIENT_SR
Return_VALUE
1
300
1
400
my query is
SELECT NAME_CLIENT , NUM_CLIENT , INV_VALUE , Return_VALUE FROM client
LEFT JOIN Invoice
ON NUM_CLIENT_INV = NUM_CLIENT
LEFT JOIN Sales returns
ON NUM_CLIENT_SR = NUM_CLIENT
The expected result is :
NAME_CLIENT
NUM_CLIENT
INV_VALUE
Return_VALUE
ALEX
1
1000
null
ALEX
1
null
300
ALEX
1
2000
null
ALEX
1
null
400
ADAM
2
null
null
but the result was given is :
NAME_CLIENT
NUM_CLIENT
INV_VALUE
Return_VALUE
ALEX
1
1000
300
ALEX
1
1000
400
ALEX
1
2000
300
ALEX
1
2000
400
ADAM
2
null
null
there is duplicate in result in columns INV_VALUE and Return_VALUE
What Is The Right Query That Give Me The expected result ?

Your existing joins return all combinations of client, optional invoice, and optional sales rows for each client.
If you want invoices and sales on separate rows, you need to join them in separate queries and union those queries. Use an inner joins so that if there are neither sales nor invoices you don't get two null/null rows, but then you have to add an extra query to get the null/null row when there are neither.
SELECT NAME_CLIENT , NUM_CLIENT , INV_VALUE , NULL as Return_VALUE FROM client
INNER JOIN Invoice
ON NUM_CLIENT_INV = NUM_CLIENT
UNION ALL
SELECT NAME_CLIENT , NUM_CLIENT , NULL , Return_VALUE FROM client
INNER JOIN Sales returns
ON NUM_CLIENT_SR = NUM_CLIENT
UNION ALL
SELECT NAME_CLIENT , NUM_CLIENT , NULL , NULL FROM client
LEFT JOIN Invoice
ON NUM_CLIENT_INV = NUM_CLIENT
LEFT JOIN Sales returns
ON NUM_CLIENT_SR = NUM_CLIENT
WHERE NUM_CLIENT_INV IS NULL AND NUM_CLIENT_SR IS NULL
ORDER BY NUM_CLIENT

Related

Required SQL Query

I have been stuck on this for sometime now.
I have the following SQL Tables:
department table
Id Name
1 DeptA
2 DeptB
3 DeptC
users table
Id Name Dept
101 Alice 2
102 Bob 3
alpha table
Id Uid Title
501 101 HELLO
502 102 HEY
503 101 SQL
beta table
Id Uid Title
601 101 HELLO1
602 101 HEY1
603 102 SQL1
Explanation:
There's basically a users table which has all the users.
Each user has a department (Dept field)
Each user has some records, linked to it with Uid, in alpha and beta tables.
The result I want:
DeptA DeptB DeptC
0 4 2
I want the count of records in alpha and beta combined, grouped by Dept of the users whose records are there in these tables.
Can someone help me with the SQL query?
As per your table structure I've used dept id for retrieving result otherwise I used dept name. You can also use COALESCE function if you get NULL
-- MySQL
SELECT SUM(CASE WHEN d.id = 1 THEN COALESCE(total, 0) END) dept_A
, SUM(CASE WHEN d.id = 2 THEN COALESCE(total, 0) END) dept_B
, SUM(CASE WHEN d.id = 3 THEN COALESCE(total, 0) END) dept_C
FROM department d
LEFT JOIN (SELECT u.dept
, COUNT(1) total
FROM users u
INNER JOIN (SELECT uid
FROM alpha
UNION ALL
SELECT uid
FROM beta) t
ON u.id = t.uid
GROUP BY u.dept ) p
ON d.id = p.dept;
Please check url http://sqlfiddle.com/#!9/020b2/1

MySQL, Remove duplicate

I need to remove duplicates from my table but MySQL is not working properly
Create table emp
( empID INT(5) PRIMARY KEY,
Pref01 int(1),
Pref02 int(1),
Pref03 int(1),
Pref04 int(1))
empID, Pref01, Pref02, Pref03, Pref04
=====================================
00011 1 2 0 0
00011 1 3 0 0
00022 1 1 0 0
00022 0 3 0 0
I need to keep these records
00011 1 3 0 0
00022 0 3 0 0
also I need to keep any record with all pref null value
this is my sql:
select empID
FROM emp
where max(Pref01) or max (Pref02) or max(Pref03) or max(Pref04)
or Pref01 is null or Pref02 is null or Pref03 is null or Pref04 is null
Your problem is quite complicated, and with given information I have to make an assumption to answer it..
Assume there is no record with same empID have same maximal pref number...
SELECT A.*
FROM emp AS A
INNER JOIN (
SELECT empID, MAX(GREATEST(Pref01, Pref02, Pref03, Pref04)) AS MaxPref
FROM emp GROUP BY empID
) AS B ON A.empID = B.empID
WHERE
(Pref01 = MaxPref OR Pref02 = MaxPref OR Pref03 = MaxPref OR Pref04 = MaxPref)
OR
(Pref01 IS NULL AND Pref02 IS NULL AND Pref03 IS NULL AND Pref04 IS NULL)
If the assumption is not correct then the code will still show duplicate for empID with same max pref number more than one.. to fix it is much more complicated than this code..
You can get your data using GROUP BY and GREATEST:
SELECT empID, max(GREATEST(Pref01, Pref02, Pref03, Pref04)) FROM emp GROUP BY empID
you can use this to find rows directly in emp table using exists or in

Need to display records join results as well as remaing qty without join

i have 3 tables. need to display records join results as well as remaing qty without join
tblBookhead
BookHeadId, bookname, bookauthor,...
tblBookDetail
BookHeaddetailId,BookHeadId,Qty
tblBookorder
orderid,BookHeaddetailId , orderqty
select * from tblBookhead bh inner join tblBookDetail bd on
bh.BookHeadId=bd.BookHeadId inner join tblBookorder br on
br.BookHeaddetailId=db.BookHeaddetailId where BookHeadId=1;
this will retrun good results no problem.
but now if qty is 10 for BookHeadId=1 and orderqty=5 then result need to display remaing 5 qty without join (my expectation is null values for remaining qty in tblBookorder )
my expected result would be:
BookHeadId, bookname, bookauthor,... BookHeaddetailId,BookHeadId,Qty,orderid,BookHeaddetailId , orderqty
1 1 john 1 1 10 1 1 5
1 1 john 1 1 10 null null null

select previous row based on group in MYSQL

I have this data.
create table #temp_student_ticket
(
student_ticket_id int identity(1,1) primary key,
student_id int ,
ticket_amount numeric(9,2)
)
insert into #temp_student_ticket
(
student_id,
ticket_amount
)
values
(
1,30.00
),(2,180.00),(1,75.00),(2,66.00)
select * from #temp_student_ticket
I need to select the previous row for the same student. Output should look like below.
student_id student_ticket_id amount prev_student_ticket_id prev_amount
1 1 20.00 NULL NULL
1 3 75.00 1 20.00
1 5 30.00 3 75.00
2 2 180.00 NULL NULL
2 4 66.00 2 180.00
What is the most optimized way to select this format on 50 million rows of table in MYSQL.
Thanks in advance.
Try this:
SELECT tst1.student_id, tst1.student_ticket_id, tst1.ticket_amount,
tst2.student_ticket_id prev_student_ticket_id, tst2.ticket_amount previous_amount
FROM temp_student_ticket tst1
LEFT JOIN temp_student_ticket tst2
ON (tst1.student_id = tst2.student_id
AND tst1.student_ticket_id > tst2.student_ticket_id
AND tst2.student_ticket_id = (SELECT MAX(tst3.student_ticket_id)
FROM temp_student_ticket tst3
WHERE tst3.student_id = tst1.student_id
AND tst3.student_ticket_id < tst1.student_ticket_id));

I need help regarding JOIN query in mysql

I have started learning MySQL and I'm having a problem with JOIN.
I have two tables: purchase and sales
purchase
--------------
p_id date p_cost p_quantity
---------------------------------------
1 2014-03-21 100 5
2 2014-03-21 20 2
sales
--------------
s_id date s_cost s_quantity
---------------------------------------
1 2014-03-21 90 9
2 2014-03-22 20 2
I want these two tables to be joined where purchase.date=sales.date to get one of the following results:
Option 1:
p_id date p_cost p_quantity s_id date s_cost s_quantity
------------------------------------------------------------------------------
1 2014-03-21 100 5 1 2014-03-21 90 9
2 2014-03-21 20 2 NULL NULL NULL NULL
NULL NULL NULL NULL 2 2014-03-22 20 2
Option 2:
p_id date p_cost p_quantity s_id date s_cost s_quantity
------------------------------------------------------------------------------
1 2014-03-21 100 5 NULL NULL NULL NULL
2 2014-03-21 20 2 1 2014-03-21 90 9
NULL NULL NULL NULL 2 2014-03-22 20 2
the main problem lies in the 2nd row of the first result. I don't want the values
2014-03-21, 90, 9 again in row 2... I want NULL instead.
I don't know whether it is possible to do this. It would be kind enough if anyone helps me out.
I tried using left join
SELECT *
FROM sales
LEFT JOIN purchase ON sales.date = purchase.date
output:
s_id date s_cost s_quantity p_id date p_cost p_quantity
1 2014-03-21 90 9 1 2014-03-21 100 5
1 2014-03-21 90 9 2 2014-03-21 20 2
2 2014-03-22 20 2 NULL NULL NULL NULL
but I want 1st 4 values of 2nd row to be NULL
Since there are no common table expressions or full outer joins to work with, the query will have some duplication and instead need to use a left join unioned with a right join;
SELECT p_id, p.date p_date, p_cost, p_quantity,
s_id, s.date s_date, s_cost, s_quantity
FROM (
SELECT *,(SELECT COUNT(*) FROM purchase p1
WHERE p1.date=p.date AND p1.p_id<p.p_id) rn FROM purchase p
) p LEFT JOIN (
SELECT *,(SELECT COUNT(*) FROM sales s1
WHERE s1.date=s.date AND s1.s_id<s.s_id) rn FROM sales s
) s
ON s.date=p.date AND s.rn=p.rn
UNION
SELECT p_id, p.date p_date, p_cost, p_quantity,
s_id, s.date s_date, s_cost, s_quantity
FROM (
SELECT *,(SELECT COUNT(*) FROM purchase p1
WHERE p1.date=p.date AND p1.p_id<p.p_id) rn FROM purchase p
) p RIGHT JOIN (
SELECT *,(SELECT COUNT(*) FROM sales s1
WHERE s1.date=s.date AND s1.s_id<s.s_id) rn FROM sales s
) s
ON s.date=p.date AND s.rn=p.rn
An SQLfiddle to test with.
In a general sense, what you're looking for is called a FULL OUTER JOIN, which is not directly available in MySQL. Instead you only get LEFT JOIN and RIGHT JOIN, which you can UNION together to get essentially the same result. For a very thorough discussion on this subject, see Full Outer Join in MySQL.
If you need help understanding the different ways to JOIN a table, I recommend A Visual Explanation of SQL Joins.
The way this is different from a regular FULL OUTER JOIN is that you're only including any particular row from either table at most once in the JOIN result. The problem being, if you have one purchase record and two sales records on a particular day, which sales record is the purchase record associated with? What is the relationship you're trying to represent between these two tables?
It doesn't sound like there's any particular relationship between purchase and sales records, except that some of them happened to take place on the same day. In which case, you're using the wrong tool for the job. If all you want to do is display these tables side by side and line the rows up by date, you don't need a JOIN at all. Instead, you should SELECT each table separately and do your formatting with some other tool (or manually).
Here's another way to get the same result, but the EXPLAIN for this is horrendous; and performance with large sets is going to be atrocious.
This is essentially two queries UNIONed together. The first query is essentially "purchase LEFT JOIN sales", the second query is essentially "sales ANTI JOIN purchase".
Because there is no foreign key relationship between the two tables, other than rows matching on date, we have to "invent" a key we can join on; we use user variables to assign ascending integer values to each row within a given date, so we can match row 1 from purchase to row 1 from sales, etc.
I wouldn't normally generate this type of result using SQL; it's not a typical JOIN operation, in the sense of how we traditionally join tables.
But, if I had to produce the specified resultset using MySQL, I would do it like this:
SELECT p.p_id
, p.p_date
, p.p_cost
, p.p_quantity
, s.s_id
, s.s_date
, s.s_cost
, s.s_quantity
FROM ( SELECT #pl_i := IF(pl.date = #pl_prev_date,#pl_i+1,1) AS i
, #pl_prev_date := pl.date AS p_date
, pl.p_id
, pl.p_cost
, pl.p_quantity
FROM purchase pl
JOIN ( SELECT #pl_i := 0, #pl_prev_date := NULL ) pld
ORDER BY pl.date, pl.p_id
) p
LEFT
JOIN ( SELECT #sr_i := IF(sr.date = #sr_prev_date,#sr_i+1,1) AS i
, #sr_prev_date := sr.date AS s_date
, sr.s_id
, sr.s_cost
, sr.s_quantity
FROM sales sr
JOIN ( SELECT #sr_i := 0, #sr_prev_date := NULL ) srd
ORDER BY sr.date, sr.s_id
) s
ON s.s_date = p.p_date
AND s.i = p.i
UNION ALL
SELECT p.p_id
, p.p_date
, p.p_cost
, p.p_quantity
, s.s_id
, s.s_date
, s.s_cost
, s.s_quantity
FROM ( SELECT #sl_i := IF(sl.date = #sl_prev_date,#sl_i+1,1) AS i
, #sl_prev_date := sl.date AS s_date
, sl.s_id
, sl.s_cost
, sl.s_quantity
FROM sales sl
JOIN ( SELECT #sl_i := 0, #sl_prev_date := NULL ) sld
ORDER BY sl.date, sl.s_id
) s
LEFT
JOIN ( SELECT #pr_i := IF(pr.date = #pr_prev_date,#pr_i+1,1) AS i
, #pr_prev_date := pr.date AS p_date
, pr.p_id
, pr.p_cost
, pr.p_quantity
FROM purchase pr
JOIN ( SELECT #pr_i := 0, #pr_prev_date := NULL ) prd
ORDER BY pr.date, pr.p_id
) p
ON p.p_date = s.s_date
AND p.i = s.i
WHERE p.p_date IS NULL
ORDER BY COALESCE(p_date,s_date),COALESCE(p_id,s_id)