How to convert code written in INNER JOIN to Subquery - mysql

Need some help with converting code from Join statement into Subquery.
I need to remove GROUP BY from it somehow, when converted into Subquery and don't know how.
Managed to put small portion of subquery at the end of the code, don't know how to do rest.
Need some help, thank you.
Here is the sample of the code: (need to convert into SQL Server syntax)
SELECT
b.Number, t.IDTyre, SUM(c.Price)
FROM Tyre AS t
INNER JOIN Bill AS b ON t.BillID = b.IDBill
INNER JOIN Customer AS c ON c.TyreID = t.IDTyre
GROUP BY b.Number, t.IDTyre
HAVING SUM(c.Price) < 3000 OR t.IDTyre NOT IN (SELECT c.TyreID FROM Customer AS c)

Check if the below query works:
SELECT
(Select b.Number From Bill AS b Where b.IDBill = t.BillID) as Number,
t.IDTyre as TyreID,
(Select SUM(c.Price) From Customer AS c Having SUM(c.Price) < 3000 OR t.IDTyre NOT IN (SELECT Distinct c.TyreID FROM Customer AS c) And c.TyreID = t.IDTyre) as Price
FROM Tyre AS t

Why are you trying to convert this to Sub Query?
JOINS are the best options while dealing with linking tables.
Also the "NOT IN" that you are trying to do at the end is also not good, you should use "NOT EXISTS". Change this to: OR NOT EXISTS (SELECT * FROM Customer AS c WHERE t.IDTyre=c.TyreID)

Related

How do I filter a SQL query by a number of relations?

I am having some problems with this homework question:
I have been able to successfully complete almost all of the query except for the "Only include states with at least 3 diamond mines". I would like to ask how I can add this part to the query.
select I.state, sum(P.capacity)
from Infrastructure I
natural join Mine M
join produces P
on P.mine = M.entryno
join Commodity C
on C.comID = P.commodity
where C.name like '%Diamond%'
group by I.state
If your attempt works fine other than condition mentioned in question following query should work:
select I.state, sum(P.capacity)
from Infrastructure I
natural join Mine M
join produces P
on P.mine = M.entryno
join Commodity C
on C.comID = P.commodity
where C.name like '%Diamond%'
group by I.state
having count(P.mine) >=3;
It will count the no. of commodity for each state as you already has group by on State.
Hope it helps!
Use a HAVING clause to count and assert the number of diamond mines:
SELECT
I.state,
SUM(P.capacity)
FROM Infrastructure I
NATURAL JOIN Mine M
INNER JOIN produces P
ON P.mine = M.entryno
INNER JOIN Commodity C
ON C.comID = P.commodity
WHERE
C.name LIKE '%Diamond%'
GROUP BY
I.state
HAVING
COUNT(*) >= 3;
Note: Natural join seems error prone to me and could break at some point. The best thing to use are explicit joins.

Mysql Joins- Results are duplicated how to fix it

I am very new to MySQL and also this is my first question if there is any mistakes please forgive me.
I have 6 tables i want to take report using this 6 tables. One of my report to access all the 6 tables and print the data as per the Query we write.Now the problem is i have write my query but this will return lot of duplicate data.How to avoid that guide me please.
SELECT
#rownum := #rownum + 1 AS RowNumber,
a.vnumber,a.vname,
b.eid,b.name,b.mobile,
c.vid,c.emp_id,c.pick_place,c.start_time,c.drop_place,c.stop_time,
c.pickupkm,c.drops,c.type_of_trip,c.travelkm,c.tamt,c.dates,
d.vid,d.emp_id,d.expcal,d.exp1,d.exp2,d.exp3,
d.exp4,d.exp5,d.expamt,d.expdesc,d.dates,
e.emp_id,e.vid,e.opeing_km,e.opeing_cash,e.closing_km,
e.closing_cash,e.opeing_date,e.opeing_time,e.closing_date,
e.closing_time, f.vid,f.emp_id,
f.totkm,f.totamt,f.expenses,f.handover_amt,
f.balance_amt,f.handover_to,f.plstatus,f.entry_date
from
add_vehicle a
LEFT JOIN third_table c ON a.vnumber=c.vid
LEFT JOIN add_employees b ON b.eid=c.emp_id
LEFT JOIN fourth_table d ON a.vnumber=d.vid
LEFT JOIN shift e ON b.eid=e.emp_id
LEFT JOIN five_table f ON a.vnumber=f.vid,
(SELECT #rownum := 0) r
WHERE
c.type_of_trip IS NOT NULL AND
c.dates BETWEEN '2017-04-01' AND '2017-04-19' AND
d.dates BETWEEN '2017-04-01' AND '2017-04-19' AND
f.entry_date BETWEEN '2017-04-01' AND '2017-04-19' AND
c.vid='STAT01' AND f.vid='STAT01' AND c.emp_id='1' AND
f.emp_id='1' AND e.emp_id='1'
ORDER BY c.dates,f.entry_date DESC
sorry for SQL fiddle not working.
This is my Tables and sample data.
My sample data
Maybe you could use "group by" by the column you wish to be unique, or use "distinct"
you can use GROUP BY function for avoiding duplicate data. Just use group by for those data whome you want to be unique. Example like below
GROUP BY eid
Add this query at the end so you can avoid same employee.
Also you can use INNER JOIN

Group Concat from a select statement

I am not sure if my method is possible, but i'm trying to do a group_concat on a select statement that concats 2 fields. I get the error: Subquery returns more than 1 row each time. Can anyone help me as to a solution, or better way around this.
select t.recnum, (select group_concat((select concat(b.origtests,'^', d.name) as testing
from order_origtests b
join profile c on c.code = b.origtests
join department d on d.recnum = c.dept
)))
FROM order_ t
You don't put SELECT inside GROUP_CONCAT. It should be
select t.recnum, (
select group_concat(concat(b.origtests,'^', d.name))
from order_origtests b
join profile c on c.code = b.origtests
join department d on d.recnum = c.dept
) AS testing
FROM order_ t
Note that your subquery isn't correlated to anything in t, so you'll get the same testing column for every recnum.

MAX() Function not working as expected

I've created sqlfiddle to try and get my head around this http://sqlfiddle.com/#!2/21e72/1
In the query, I have put a max() on the compiled_date column but the recommendation column is still coming through incorrect - I'm assuming that a select statement will need to be inserted on line 3 somehow?
I've tried the examples provided by the commenters below but I think I just need to understand this from a basic query to begin with.
As others have pointed out, the issue is that some of the select columns are neither aggregated nor used in the group by clause. Most DBMSs won't allow this at all, but MySQL is a little relaxed on some of the standards...
So, you need to first find the max(compiled_date) for each case, then find the recommendation that goes with it.
select r.case_number, r.compiled_date, r.recommendation
from reporting r
join (
SELECT case_number, max(compiled_date) as lastDate
from reporting
group by case_number
) s on r.case_number=s.case_number
and r.compiled_date=s.lastDate
Thank you for providing sqlFiddle. But only reporting data is given. we highly appreciate if you give us sample data of whole tables.
Anyway, Could you try this?
SELECT
`case`.number,
staff.staff_name AS ``case` owner`,
client.client_name,
`case`.address,
x.mx_date,
report.recommendation
FROM
`case` INNER JOIN (
SELECT case_number, MAX(compiled_date) as mx_date
FROM report
GROUP BY case_number
) x ON x.case_number = `case`.number
INNER JOIN report ON x.case_number = report.case_number AND report.compiled_date = x.mx_date
INNER JOIN client ON `case`.client_number = client.client_number
INNER JOIN staff ON `case`.staff_number = staff.staff_number
WHERE
`case`.active = 1
AND staff.staff_name = 'bob'
ORDER BY
`case`.number ASC;
Check below query:
SELECT c.number, s.staff_name AS `case owner`, cl.client_name,
c.address, MAX(r.compiled_date), r.recommendation
FROM case c
INNER JOIN (SELECT r.case_number, r.compiled_date, r.recommendation
FROM report r ORDER BY r.case_number, r.compiled_date DESC
) r ON r.case_number = c.number
INNER JOIN client cl ON c.client_number = cl.client_number
INNER JOIN staff s ON c.staff_number = s.staff_number
WHERE c.active = 1 AND s.staff_name = 'bob'
GROUP BY c.number
ORDER BY c.number ASC
SELECT
case.number,
staff.staff_name AS `case owner`,
client.client_name,
case.address,
(select MAX(compiled_date)from report where case_number=case.number),
report.recommendation
FROM
case
INNER JOIN report ON report.case_number = case.number
INNER JOIN client ON case.client_number = client.client_number
INNER JOIN staff ON case.staff_number = staff.staff_number
WHERE
case.active = 1 AND
staff.staff_name = 'bob'
GROUP BY
case.number
ORDER BY
case.number ASC
try this

mysql subquery returns more than 1 row

I have the following query :
(select xyz.* from
(select xt.image, p.*, pc.categoryid, c.category,
(select value from xcart_extra_field_values
where efv.productid=p.productid and efv.fieldid = 2) as Type,
(select value from xcart_extra_field_values
where efv.productid=p.productid and efv.fieldid = 1) as Zone
FROM xcart_products p
inner join xcart_products_categories pc
on p.productid=pc.productid
inner join xcart_categories c
on pc.categoryid=c.categoryid
inner join xcart_extra_field_values efv
on p.productid=efv.productid
inner join xcart_images_T xt
on p.productid=xt.id) xyz
where categoryid='1' and Type='2' and Zone='1'
group by productid)
But when I execute this query in phpmyadmin it displays a error messgae :
#1242 - Subquery returns more than 1 row
Whats wrong in the query.Please help. Thanks in advance.
I think (part of) the problem is that you are re-using an alias in a wrong location.
You should one use an alias once, and don't mix them for different instances of the same table.
(select xyz.* from
(select xt.image, p.*, pc.categoryid, c.category,
(select value from xcart_extra_field_values efv2
where efv2.productid=p.productid and efv2.fieldid = 2) as Type,
(select value from xcart_extra_field_values efv3
where efv3.productid=p.productid and efv3.fieldid = 1) as Zone
FROM xcart_products p
inner join xcart_products_categories pc
on p.productid=pc.productid
inner join xcart_categories c
on pc.categoryid=c.categoryid
inner join xcart_extra_field_values efv1
on p.productid=efv1.productid
inner join xcart_images_T xt
on p.productid=xt.id) xyz
where categoryid='1' and Type='2' and Zone='1'
group by productid)
So use a unique alias efvx for each xcart_extra_field_values table instance.
Execute each subquery manually in phpmyadmin and see which one is returning more than one row and you have your answer. Another option is to add a limit of 1 to each subquery to make sure only one row is returned. Of course it is better to look for the bug and solve it.