How to build a complex sql query? - sql

Database design here
I want to get records from the product_spec_data table that are associated with products whose category_id is 5.
Please help me make a query to the database...

All of the relationship are clearly laid out, a simple join across tables would works.
SELECT psd.*
FROM product_spec_data psd
INNER JOIN product_spec_values psv ON psd.id = psv.product_spec_data_id
INNER JOIN products prod ON psv.product_id = prod.id
INNER JOIN categories cat ON prod.category_id = cat.id
-- with category id = 5
WHERE cat.id = 5;

I am not sure what do you mean by complex query. I guess your question is not complete. I think the query for your question (if it is T-SQL) will be as follows
select d.*
from product_spec_data d
left outer join product_spec_values v on d.id=v.product_spec_data_id
left outer join products p on v.product_id=p.id
where p.category_id=5
(I think in MySQL also above syntax will remain same, you may remove [outer] clause in MySQL)

Related

Is it true that all joins following a left join in a SQL query must also be left joins? Why or why not?

I remember this rule of thumb from back in college that if you put a left join in a SQL query, then all subsequent joins in that query must also be left joins instead of inner joins, or else you'll get unexpected results. But I don't remember what those results are, so I'm wondering if maybe I'm misremembering something. Anyone able to back me up on this or refute it? Thanks! :)
For instance:
select * from customer
left join ledger on customer.id= ledger.customerid
inner join order on ledger.orderid = order.id -- this inner join might be bad mojo
Not that they have to be. They should be (or perhaps a full join at the end). It is a safer way to write queries and express logic.
Your query is:
select *
from customer c left join
ledger l
on c.id = l.customerid inner join
order o
on l.orderid = o.id
The left join says "keep all customers, even if there is no matching record in ledger. The second says, "I have to have a matching ledger record". So, the inner join converts the first to an inner join.
Because you presumably want all customers, regardless of whether there is a match in the other two tables, you would use a left join:
select *
from customer c left join
ledger l
on c.id = l.customerid left join
order o
on l.orderid = o.id
You remember correctly some parts of it!
The thing is, when you chain join tables like this
select * from customer
left join ledger on customer.id= ledger.customerid
inner join order on ledger.orderid = order.id
The JOIN is executed sequentialy, so when customer left join ledger happens, you are making sure all joined keys from customer return (because it's a left join! and you placed customers to the left).
Next,
The results of the former JOIN are joined with order (using inner join), forcing the "the first join keys" to match (1 to 1) with the keys from order so you will end up only with records that were matched in order table as well
Bad mojo? it really depends on what you are trying to accomplish.
If you want to guarantee all records from customers return, you should keep "left joining" to it.
You can, however, make this a little more intuitive to understand (not necessarily a better way of writing SQL!) by writing:
SELECT * FROM
(
(SELECT * from customer) c
LEFT JOIN
(SELECT * from ledger) l
ON
c.id= l.customerid
) c_and_l
INNER JOIN (OR PERHAPS LEFT JOIN)
(SELECT * FROM order) as o
ON c_and_l.orderid (better use c_and_l.id as you want to refer to customerid from customers table) = o.id
So now you understand that c_and_l is created first, and then joined to order (you can imagine it as 2 tables are joining again)

How to reduce execution time of a select query

I have a query which is given below. My doubt is regarding its record fetching time. Is there any better way to fetch records than this method?
select product_code,product_name,price,taxPercentage,discount_type,discount_amount,prof it_type,profit_amount,purchase_code, qty
from (
select distinct p.product_code,p.product_name,pid.price,t.percentage as taxPercentage,p.discount_type,p.discount_amount,p.profit_type,p.profit_amount,
pu.purchase_code,pid.quantity+isnull(sum(sri.quantity),0) -isnull(sum(si.quantity),0) -isnull(sum(pri.quantity),0) as qty
from tbl_product p
left join tbl_purchase_item pid on p.product_code=pid.product_code
left join tbl_purchase pu on pu.purchase_code=pid.purchase_code
left join tbl_tax t on t.tax_code=p.tax_code
left join tbl_sale_item si on si.product_code=p.product_code
left join tbl_sale s on s.sale_code=si.sale_code
left join tbl_sale_return sr on sr.sale_code=s.sale_code
left join tbl_sale_return_item sri on sri.sale_return_code=sr.sale_return_code
left join tbl_purchase_return_item pri on pri.purchase_code=pu.purchase_code
group by p.product_code,p.product_name,pid.price,t.percentage,p.discount_type,p.discount_amount,p.profit_type,p.profit_amount,pu.purchase_code,pid.quantity
) as abc
where qty >0
I do not know how your database looks like. You have too many joins and I guess that is the root of the slowness.
First, make sure you have indexed all the columns used in the joins.
If that does not help, try to do some Denormalization. That way you will introduce some redundancy in your database, but the read time will improve.
Join Smaller table with larger table
consider an index on the table

Postgres SQL inner join syntax

Can some one please explain the inner join syntax in the SQL below:
CREATE TABLE dataset AS
SELECT property.id
, amount.band
, amount."value"
FROM property
INNER JOIN (locality INNER JOIN amount ON locality.code = amount.code) ON (property.band = amount.band) AND (property.id = locality."UniqueId")
Why is the table locality defined before the second inner join? I've never come across such strange syntax.
Is there a more clearer way to right the same query so that someone can easily understand whats going on?
FROM property
INNER JOIN (locality INNER JOIN amount ON locality.code = amount.code)
ON (property.band = amount.band) AND (property.id = amount."UniqueId")
is the same as
FROM property
INNER JOIN amount ON property.band = amount.band AND property.id = amount."UniqueId"
INNER JOIN locality ON locality.code = amount.code
When INNER JOINs only, you can re-order them as you want.
(Any specific reason to JOIN locality? You don't select any of its columns. Is it some kind of EXISTS, or do you want multiple rows returned if there are several matching rows in that table?)

Joining 3 tables in sql-server

I have three tables in sql-server like table A table B table C.
How can I join 3 tables as expressed in the image below?
More information needed to give you a correct piece of code, but from the image you need LEFT JOINs.
(ID's have been presumed)
SELECT *
FROM Customers c
LEFT JOIN Items i ON c.iid = i.id
LEFT JOIN Sales s ON c.sid = s.id
It's never too late :)
Most probably you'll need this:
select ...
from customers
full outer join (items inner join sales on (xxx)) on (xxx)

how to join these tables in sql

I have these tables and would like to query them to show the all clients and their groups (if any), the following image describes the case:
How to join tables to get the result using sql server?
This looks like a lesson teaching CROSS JOIN. Because you want a row in your result for each intersection of client and group, whether or not it is valid, you want to cross join those tables then see if there is a matching record in client_group. In a working application this cross join could get unwieldy very quickly, with a few thousand groups and clients you'd have many millions of results.
Something like this should get your cartesian result and see if a matching record is found:
SELECT
c.id 'client_id', g.Id 'group_id', ISNULL(cg.client_id)
FROM
(client c
CROSS JOIN group g)
LEFT JOIN client_group cg ON c.id = cg.client_id AND g.id = cg.group_id
More on joining:
What is the difference between Left, Right, Outer and Inner Joins?