MySQL: From sub query to a single query - mysql

I have this query which i believe can be optimized:
SELECT floors.id, floors.floor FROM floors
WHERE floors.societies_id = 1
AND floors.status = 'Y'
AND floors.id NOT IN (
SELECT DISTINCT(floors.id) FROM floors
INNER JOIN societies ON societies.id = floors.societies_id
INNER JOIN resident_floors ON resident_floors.floors_id = floors.id
WHERE societies.id = 1
AND floors.status = 'Y'
)
Is this query fine to use or there it can be improved..?

It looks like you want to get all floors that aren't present in resident_floors. For this we can left join RF in and ask for only rows where the join failed resulting in a null in RF:
SELECT floors.* FROM floors
INNER JOIN societies ON societies.id = floors.societies_id
LEFT JOIN resident_floors ON resident_floors.floors_id = floors.id
WHERE societies.id = 1
AND floors.status = 'Y'
AND resident_floors.floors_id IS NULL

Related

error subquery return more than 1 when doing multiple select

I want to do a multiple select in one query with different conditions. but somehow i'm stuck in this problem. any idea?
SELECT
(select io_link_event_names.name from doors left join controller_devices on doors.iid = controller_devices.iid left join events on controller_devices.mac = events.mac left join io_link_event_names on events.iolinkerid = io_link_event_names.extra where events.iolinkerid = "9000;1") AS forced,
(select doors.name FROM doors) AS doorname
ERROR #1242 - Subquery returns more than 1 row
consider this
SELECT d.[forced], doors.name as doorname
from doors
left join (
select controller_devices.iid, io_link_event_names.name as [forced]
from events
inner join controller_devices on controller_devices.mac = events.mac
inner join io_link_event_names on events.iolinkerid = io_link_event_names.extra
where events.iolinkerid = "9000;1"
) as d on d.iid = doors.iid
If you have more than 1 row in table doors, you get this error. If you want too see door name relevant to event selected in first query, use
select io_link_event_names.name,
doors.name doorname
from doors
left join controller_devices
on doors.iid = controller_devices.iid
left join events
on controller_devices.mac = events.mac
left join io_link_event_names
on events.iolinkerid = io_link_event_names.extra
where events.iolinkerid = "9000;1"

Mysql Fetching rows base on date

Here's the code:
SELECT RD.INTREQDQUANTITY, I.strItemName, v.strVendName, iu.strItemUnitName,
ip.dblItemPAmount, MAX(ip.dtmItemPasOf) AS EXR
FROM TBLREQUESTDETAILS RD,tblitem I,tblvendor v,tblitemunit iu,tblitemprice ip`
WHERE RD.strReqDItemCode = I.strItemCode
AND RD.strReqDItemUnitCode = iu.strItemUnitCode
AND RD.strReqDVendCode = v.strVendCode
AND i.strItemCode = ip.strItemPItemCode
and RD.strReqDReqHCode = 'RQST121'
GROUP BY RD.INTREQDQUANTITY,I.strItemName,v.strVendName,iu.strItemUnitName, ip.dblItemPAmount
ORDER BY EXR desc ;
AND Here's The result:
What should I do If I want to fetch the current price for each itemname,vendorname and itemunit?? I want to fetch only those rows who's price is the Latest... Help me please those with boxes are the rows that i want to fetch
You can use where in the grouped value (and use explicict join notatio)
SELECT RD.INTREQDQUANTITY, I.strItemName, v.strVendName, iu.strItemUnitName,
ip.dblItemPAmount, ip.dtmItemPasOf AS EXR
FROM TBLREQUESTDETAILS RD
INNER JOIN tblitem I ON RD.strReqDItemCode = I.strItemCode
INNER JOIN tblvendor v ON D.strReqDVendCode = v.strVendCode
INNER JOIN tblitemunit iu ON RD.strReqDItemUnitCode = iu.strItemUnitCode
INNER JOIN tblitemprice ip ON i.strItemCode = ip.strItemPItemCode
WHERE RD.strReqDReqHCode = 'RQST121'
and ( RD.INTREQDQUANTITY, I.strItemName, v.strVendName, iu.strItemUnitName, ip.dtmItemPasOf)
in ( SELECT RD.INTREQDQUANTITY, I.strItemName, v.strVendName, iu.strItemUnitName,
MAX(ip.dtmItemPasOf)
FROM TBLREQUESTDETAILS RD
INNER JOIN tblitem I ON RD.strReqDItemCode = I.strItemCode
INNER JOIN tblvendor v ON D.strReqDVendCode = v.strVendCode
INNER JOIN tblitemunit iu ON RD.strReqDItemUnitCode = iu.strItemUnitCode
INNER JOIN tblitemprice ip ON i.strItemCode = ip.strItemPItemCode
WHERE RD.strReqDReqHCode = 'RQST121'
GROUP BY RD.INTREQDQUANTITY,I.strItemName,v.strVendName,iu.strItemUnitName
)
ORDER BY EXR desc ;
(and use explicict join notation .. i think is more readable)

mysql inner join return null value,

SELECT `mpeda_fish`.`id`, `mpeda_fish`.`fish` as analysis, sum(mpeda_fishdetails.quantity) as qty
FROM (`mpeda_fishdetails`)
INNER JOIN `mpeda_scientificfish` ON `mpeda_scientificfish`.`id` = `mpeda_fishdetails`.`scientificfish`
INNER JOIN `mpeda_fish` ON `mpeda_fish`.`id` = `mpeda_scientificfish`.`fish`
INNER JOIN `mpeda_fishcatch` ON `mpeda_fishcatch`.`id` = `mpeda_fishdetails`.`fishcatch`
INNER JOIN `mpeda_harbour` ON `mpeda_harbour`.`id` = `mpeda_fishcatch`.`harbour`
WHERE `mpeda_fishcatch`.`status` = 1
ORDER BY `mpeda_fishdetails`.`id` ASC
this query gets 2 columns null value and one column gets data inside why?
You use the SUM() function. In order to get meaningful results you should have a group by clause.
SELECT `mpeda_fish`.`id`, `mpeda_fish`.`fish` as analysis, sum(mpeda_fishdetails.quantity) as qty
FROM (`mpeda_fishdetails`)
INNER JOIN `mpeda_scientificfish` ON `mpeda_scientificfish`.`id` = `mpeda_fishdetails`.`scientificfish`
INNER JOIN `mpeda_fish` ON `mpeda_fish`.`id` = `mpeda_scientificfish`.`fish`
INNER JOIN `mpeda_fishcatch` ON `mpeda_fishcatch`.`id` = `mpeda_fishdetails`.`fishcatch`
INNER JOIN `mpeda_harbour` ON `mpeda_harbour`.`id` = `mpeda_fishcatch`.`harbour`
WHERE `mpeda_fishcatch`.`status` = 1
GROUP BY `mpeda_fish`.`id`, `mpeda_fish`.`fish`
ORDER BY `mpeda_fishdetails`.`id` ASC

using joins together with aggregates, and retrieving rows when no aggregate exists

The following query on my MySQL tables returns rows from the purchaseorder table that have corresponding entries in the deliveryorder table. How do I construct this query so that I get rows from the purchaseorder table even if no corresponding rows exist in the deliveryorder table? If the users want to see sql table CREATE statements, I can post those, but I'm not posting now as it really makes the question too big.
SELECT
`purchaseorder`.`id` AS `po_id`,
`purchaseorder`.`order_quantity` AS `po_order_quantity`,
`purchaseorder`.`applicable_approved_unit_rate` AS `po_unit_rate`,
`purchaseorder`.`applicable_sales_tax_rate` AS `po_tax_rate`,
`purchaseorder`.`order_date` AS `po_order_date`,
`purchaseorder`.`remarks` AS `po_remarks`,
`purchaseorder`.`is_open` AS `po_is_open`,
`purchaseorder`.`is_active` AS `po_is_active`,
`purchaseorder`.`approved_rate_id` AS `po_app_rate_id`,
`supplier`.`name` AS `sup_name`,
SUM(`deliveryorder`.`quantity`) AS `total_ordered`
FROM `purchaseorder`
LEFT JOIN `deliveryorder` ON (`deliveryorder`.`purchase_order_id` = `purchaseorder`.`id`)
INNER JOIN `approvedrate` ON (`purchaseorder`.`approved_rate_id` = `approvedrate`.`id`)
INNER JOIN `supplier` ON (`approvedrate`.`supplier_id` = `supplier`.`id`)
WHERE (
`purchaseorder`.`is_active` = 1
AND `purchaseorder`.`is_open` = 1
AND `deliveryorder`.`is_active` = 1
AND `approvedrate`.`material_id` = 2
)
HAVING `purchaseorder`.`order_quantity` >= `total_ordered` + 1
You have an aggregating function but no GROUP BY clause, which is wierd, but anyway - something like this? Oops - edited...
SELECT po.id po_id
, po.order_quantity po_order_quantity
, po.applicable_approved_unit_rate po_unit_rate
, po.applicable_sales_tax_rate po_tax_rate
, po.order_date po_order_date
, po.remarks po_remarks
, po.is_open po_is_open
, po.is_active po_is_active
, po.approved_rate_id po_app_rate_id
, s.name sup_name
, SUM(do.quantity) total_ordered
FROM purchaseorder po
LEFT
JOIN deliveryorder do
ON do.purchase_order_id = po.
AND do.is_active = 1
LEFT
JOIN approvedrate ar
ON ar.id = po.approved_rate_id
AND ar.material_id = 2
LEFT
JOIN supplier s
ON s.id = ar.supplier_id
WHERE po.is_active = 1
AND po.is_open = 1
HAVING po.order_quantity >= total_ordered + 1
I couldn't work out how to get the desired results all in one query, but ended up using the following two queries to fulfill my requirements: -
1st query
SELECT
pot.`id` AS `po_id`,
pot.`order_quantity` AS `po_order_quantity`,
pot.`applicable_approved_unit_rate` AS `po_unit_rate`,
pot.`applicable_sales_tax_rate` AS `po_tax_rate`,
pot.`is_open` AS `po_is_open`,
pot.`is_active` AS `po_is_active`,
st.`id` AS `sup_id`,
st.`name` AS `sup_name`,
SUM(dot.`quantity`) AS `total_ordered`
FROM `purchaseorder` pot
INNER JOIN `deliveryorder` dot ON (dot.`purchase_order_id` = pot.`id`)
INNER JOIN `approvedrate` art ON (pot.`approved_rate_id` = art.`id`)
INNER JOIN `supplier` st ON (art.`supplier_id` = st.`id`)
WHERE (
pot.`is_active` = 1
AND pot.`is_open` = 1
AND art.`material_id` = #materialid
AND art.`in_effect` = 1
AND art.`is_active` = 1
AND dot.`is_active` = 1
AND st.`is_active` = 1
)
HAVING pot.`order_quantity` >= `total_ordered` + #materialquantity
2nd query
SELECT
pot.`id` AS `po_id`,
pot.`order_quantity` AS `po_order_quantity`,
pot.`applicable_approved_unit_rate` AS `po_unit_rate`,
pot.`applicable_sales_tax_rate` AS `po_tax_rate`,
pot.`is_open` AS `po_is_open`,
pot.`is_active` AS `po_is_active`,
st.`id` AS `sup_id`,
st.`name` AS `sup_name`,
0 AS `total_ordered`
FROM `purchaseorder` pot
INNER JOIN `approvedrate` art ON (pot.`approved_rate_id` = art.`id`)
INNER JOIN `supplier` st ON (art.`supplier_id` = st.`id`)
WHERE (
pot.`is_active` = 1
AND pot.`is_open` = 1
AND art.`material_id` = #materialid
AND art.`in_effect` = 1
AND art.`is_active` = 1
AND st.`is_active` = 1
AND pot.`order_quantity` >= #materialquantity
AND pot.`id` NOT IN
(
SELECT dot.`purchase_order_id`
FROM `deliveryorder` dot
WHERE dot.is_active = 1
)
)

MySQL join only selected rows

SELECT invoices.number_formatted, SUM(invoices_elements.netto)
FROM invoices
LEFT JOIN invoices_elements ON invoices_elements_code_invoices_id = invoices_id
WHERE invoices_enable = 1
AND invoices_elements_enable = 1
GROUP BY invoices_elements_code_invoices_id
If table "invoices_elements" doesn't have any rows with "invoices_elements_enable = 1" this query return NULL - but i want "number formatted". So i do this:
SELECT SUM(netto)
FROM (invoices)
LEFT JOIN (SELECT * FROM invoices_elements WHERE invoices_elements_enable = 1) ON invoices_elements_code_invoices_id = invoices_id
WHERE invoices_enable = 1
GROUP BY invoices_elements_code_invoices_id
... and this of coz works. But - is better way to do it?
You can do
SELECT SUM(netto)
FROM invoices
LEFT JOIN invoices_elements
ON invoices_elements_code_invoices_id = invoices_id
AND invoices_elements_enable = 1
WHERE invoices_enable = 1
GROUP BY invoices_elements_code_invoices_id
Note the restriction invoices_elements_enable = 1 is in the ON clause to avoid converting the query into an inner join.