I have two tables
Table 1 = restaurants ( r_id , type , cuisine_bkup )
Table 2 = address ( id , r_id , location, address )
I am applying this query
SELECT *
FROM restaurants r
RIGHT JOIN addresses a ON a.r_id = r.r_id
WHERE r.type LIKE 'Cafe' AND a.location LIKE 'Gulberg' AND r.cuisine_bkup LIKE 'Pizza'
GROUP BY r.r_id
Its giving me no result what should i do i want to do it with AND condition
You probably need the wildcard character % to search the values in your column like this:
SELECT *
FROM restaurants r
RIGHT JOIN addresses a ON a.r_id = r.r_id
WHERE r.type LIKE '%Cafe%' AND a.location LIKE '%Gulberg%' AND r.cuisine_bkup LIKE '%Pizza%'
GROUP BY r.r_id
else the other option(which I am guessing is to use an OR instead of AND)
SELECT *
FROM restaurants r
RIGHT JOIN addresses a ON a.r_id = r.r_id
WHERE r.type LIKE '%Cafe%' OR a.location LIKE '%Gulberg%' OR r.cuisine_bkup LIKE '%Pizza%'
GROUP BY r.r_id
(Also to note that you will get the result for your AND when and only when all the three conditions are TRUE ie, r.type LIKE 'Cafe' AND a.location LIKE 'Gulberg' AND r.cuisine_bkup LIKE 'Pizza')
Use % with like
WHERE r.type LIKE '%Cafe%'
AND a.location LIKE '%Gulberg%'
AND r.cuisine_bkup LIKE '%Pizza%'
SELECT *
FROM restaurants r
RIGHT JOIN addresses a ON a.r_id = r.r_id AND a.location LIKE 'Gulberg'
WHERE r.type LIKE 'Cafe' AND r.cuisine_bkup LIKE 'Pizza'
GROUP BY r.r_id
To make RIGHT join work , you have to move AND a.location LIKE 'Gulberg' to ON section.Otherwise it will function as INNER JOIN.
I would like to point out that '=' will work much faster than LIKE(If you are equating characters)..
Hope this helps
Related
I have 3 column here in tblItem
purchase
stock
calculate
and this 3 column have to join with tblMeasurement
name
I have tried this, but when I display 3 columns show the same all.
SQL
$sql = "SELECT A.itemID, A.categoryID, A.purchaseMeasurementID, A.stockMeasurementID, A.calculationMeasurementID, A.itemName, B.itemCategoryName, C.measurementName
FROM tblPurItem A
LEFT JOIN tblPurItemCategory B
ON A.categoryID = B.itemcategoryID
LEFT JOIN tblPurMeasurement C
ON A.purchaseMeasurementID= C.measurementID";
As you see my sql above, it has join only for purchaseMeasurementID. How do I join stockMeasurementID and calculationMeasurementID based on also tblPurMeasurement ? Is there any missing here?
Try using this subquery instead.
SELECT A.itemID, A.categoryID, A.purchaseMeasurementID, A.stockMeasurementID, A.calculationMeasurementID, A.itemName
, (select B.itemCategoryName from tblPurItemCategory B where A.categoryID = B.itemcategoryID limit 1) as itemCategoryName
, (select C.measurementName from tblPurMeasurement C where A.purchaseMeasurementID= C.measurementID limit 1) as purchasemeasurementName
, (select C.measurementName from tblPurMeasurement C where A.stockMeasurementID= C.measurementID limit 1) as stockmeasurementName
, (select C.measurementName from tblPurMeasurement C where A.calculationMeasurementID= C.measurementID limit 1) as calculationmeasurementName
FROM tblPurItem A
I try to improve this query but I do not made successefully. I use a some left join and subquerys (I don't know another form) We try to get all bookings from users with certain status and the number of bookings multiples related with this booking and get from the log user the origin. The query is slow even if use a limit clausure. I Appreciate all the help can you give me.
This is the query:
SELECT DISTINCT b.uneaque_id, b.id, b.status, b.route_status, b.username, b.purpose, b.transfer, b.pickup_date, b.pickup_time, b.return_time, b.amount, b.default_location, b.start_address_route_comments, b.start_address_route, b.end_address_route_comments, b.end_address_route, u1.first_name, u1.last_name, b.transaction_Id, b.manual_payment, mr.AddressCount, lu.origin
FROM bookingdetails b
LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING'
LEFT JOIN (
SELECT booking_id, COUNT(*) AS AddressCount FROM booking_multiple_rides GROUP BY booking_id
) mr ON b.id = mr.booking_id,
userdetails u1 WHERE b.username = u1.email
AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
AND b.default_location = 1
PD: Sorry for my english.
You have a ON b.id = mr.booking_id, userdetails u1 WHERE
you should change with a proper inner join
SELECT DISTINCT b.uneaque_id
, b.id, b.status
, b.route_status
, b.username
, b.purpose
, b.transfer
, b.pickup_date
, b.pickup_time
, b.return_time
, b.amount
, b.default_location
, b.start_address_route_comments
, b.start_address_route
, b.end_address_route_comments
, b.end_address_route
, u1.first_name
, u1.last_name
, b.transaction_Id
, b.manual_payment
, mr.AddressCount
, lu.origin
FROM bookingdetails b
LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING'
LEFT JOIN (
SELECT booking_id
, COUNT(*) AS AddressCount
FROM booking_multiple_rides GROUP BY booking_id
) mr ON b.id = mr.booking_id
INNER JOIN userdetails u1 ON b.username = u1.email
AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
AND b.default_location = 1
and be sure you have proper index on
table bookingdetails a composite index on columns ( uneaque_id , id, default_location)
table log_users a composite index on columns (uneaque_id, command_type)
table userdetails a cmposite index on columns (email,user_status )
Tip 1.
Hiding a derived table in a LEFT JOIN is a prescription for sluggishness.
Replace
mr.AddressCount
with
( SELECT COUNT(*)
FROM booking_multiple_rides
WHERE booking_id = b.id
GROUP BY booking_id ) AS AddressCount
and get rid of the LEFT JOIN ( SELECT ... ) AS mr ON ..
Tip 2 Use explicit JOINs, no the old-fashioned "comma-join":
JOiN userdetails u1
ON b.username = u1.email
This won't help performance but it will make things clearer.
Tip 3: If you need an INNER JOIN (u1) after a LEFT JOIN, use parentheses. Else, put the inner joins first, then the left joins. This makes it easier to use, but may screw up the logic.
Tip 4: Don't use LEFT unless you need it. When you dont need it, it confuses the reader (and the Optimizer). (Again, no performance change.)
Tip 5: Why are you using DISTINCT? That takes an extra pass over all the resultset.
If those do not help enough, then provide SHOW CREATE TABLE so we can critique the indexes.
left say for instance that I have the following query and want to limit the left join on a table, how do I achieve that?
SELECT * FROM Base
LEFT JOIN Derived1 ON Base.id = Derived1.id
LEFT JOIN Derived2 ON Base.id = Derived2.id
LEFT JOIN Derived3 ON (Base.id = Derived3.id WHERE Derived3.name LIKE 'test%' LIMIT 5) <-----
WHERE Base.id = 'someid';
I though I could write it like this:
SELECT * FROM Base
LEFT JOIN Derived1 ON Base.id = Derived1.id
LEFT JOIN Derived2 ON Base.id = Derived2.id
LEFT JOIN Derived3 ON Base.id = (
SELECT d3.id FROM Derived3 d3
WHERE d3.name LIKE 'test%' AND Base.id = Derived3.id
LIMIT 5
)
WHERE Base.id = 'someid';
but this gives me the incorrect result
I want all data which is inside Derived3 but only 5 items if Derived.name equals to test 1, test 2, test 3 etc.
There might be 100 000 000 tests inside that tables and a couple of thousand other stuff which doesn't start with 'test'.
So basically, give me anything inside Derived3 and max 5 rows that start with 'test'.
How do I solve this?
Check the bellow query.
SELECT *
FROM Base
LEFT JOIN Derived1 ON Base.id = Derived1.id
LEFT JOIN Derived2 ON Base.id = Derived2.id
LEFT JOIN Derived3 ON (
Base.id = Derived3.id
AND Derived3.id IN (
SELECT Derived3.id
FROM Derived3
WHERE Derived3.NAME LIKE 'test%' LIMIT 5
)
)
WHERE Base.id = 'someid'
I'm not sure if this can fit in your scenario but you can select from Derived3 using filter LIKE 'test%' and join the select result using alias.
I don't have MySql installed to try this but something like this should work:
SELECT * FROM Base
LEFT JOIN Derived1 ON Base.id = Derived1.id
LEFT JOIN Derived2 ON Base.id = Derived2.id
LEFT JOIN (
SELECT d3.id FROM Derived3 d3
WHERE d3.name LIKE 'test%'
LIMIT 5
) Derived3Alias ON Base.id = Derived3Alias.id
WHERE Base.id = 'someid'
GROUP BY Base.id;
Maybe you will need to write "as Derived3Alias" but try first without 'as' I think it should work.
I am trying to get the due_amount from two tables that is invoices and offline_invoice.
The condition is; status not like 'paid%'. I am working with this query
select
(sum(i.total_amount) + sum(oi.invoice_amount)) - (sum(i.paid_amount) + sum(oi.paid_amount)) due_amount
from
{CI}invoices i
left join
{CI}offline_invoice oi ON oi.customer_id = i.customer_id
where
i.customer_id = ?
and i.status not like 'paid%'
group by i.customer_id
But i don't know how do i use condition on joined table({CI}offline_invoice)? I have to use the same condition(status not like 'paid%') on it.
Just add the and to the ON clause too
left join
{CI}offline_invoice oi ON oi.customer_id = i.customer_id
AND oi.status not like 'paid%'
where
i.customer_id = ?
and i.status not like 'paid%'
However, I'm not sure how this is going to work for you without possible Cartesian impact. Say you have 10 current invoice and 10 and 6 offline invoices. I would do two separate pre-aggregates joined by their customer ID... unless the off-line invoice has the same invoice ID as current (such as archive purposes)
select
CurInvoices.Customer_ID,
CurInvoices.InvBalance + COALESCE( OIInvoices.OIBalance, 0 ) as AllBalanceDue
from
( select i.customer_id,
sum( i.total_amount - i.paid_amount ) as invBalance
from
{CI}invoices i
where
i.customer_id = ?
and i.status not like 'paid%'
group by
i.customer_ID ) as CurInvoices
LEFT JOIN
( select oi.customer_id,
sum( oi.total_amount - oi.paid_amount ) as OIBalance
from
{CI}offline_invoice oi
where
oi.customer_id = ?
and oi.status not like 'paid%'
group by
i.customer_ID ) as OIInvoces
on CurInvoices.Customer_ID = OIInvoices.customer_ID
I have following SQL query but this is not quite what I want:
SELECT
TOP (20) Attribs.ImageID AS ItemID
FROM
Attribs
LEFT OUTER JOIN
Items ON Attribs.ImageID = Items.ImageID
WHERE
(attribID IN ('a','b','c','d','e'))
AND (deleted NOT IN (1,2))
AND Attribs.attribID = 'a' AND Attribs.attribID = 'b'
GROUP BY
Attribs.ImageID
ORDER BY
COUNT(DISTINCT attribID) DESC
What I need is to query
AND Attribs.attribID = 'a' AND Attribs.attribID = 'b'
first, then rest of the WHERE clause based on the above query results.
Is this possible to achieve using sub query?
I'm using SQL Server 2008
Thank you
I'm not totally getting the reason why you want to do this one query first before the other.... but you could use a Common Table Expression (CTE) - something like this:
;WITH FirstQuery AS
(
SELECT a.ImageId
FROM dbo.Attribs a
WHERE a.attribID = 'a' AND a.attribID = 'b'
)
SELECT
TOP (20) a.ImageID AS ItemID
FROM
dbo.Attribs a
INNER JOIN
FirstQuery fq ON a.ImageId = fq.ImageId
LEFT OUTER JOIN
dbo.Items i ON a.ImageID = i.ImageID
WHERE
(attribID IN ('a','b','c','d','e'))
AND (deleted NOT IN (1,2))
GROUP BY
a.ImageID
ORDER BY
COUNT(DISTINCT attribID) DESC
With this, you first select the ImageID from your dbo.Attribs table in the CTE, and then join that result set with the result of the table and join to the Items table.
You want to do that for performance issues? Because splitting this up won't change the results.
Anyway, you can do this like:
SELECT TOP (20) rn_Attribs.ImageID AS ItemID
FROM (SELECT *
FROM Attribs
WHERE Attribs.attribID = '123' AND Attribs.attribID = '456') rn_Attribs
LEFT OUTER JOIN Items ON rn_Attribs.ImageID = Items.ImageID
WHERE(attribID IN ('a','b','c'))
AND (deleted NOT IN (1,2))
GROUP BY rn_Attribs.ImageID
ORDER BY COUNT(DISTINCT attribID) DESC