GROUP BY not working in left join query - sql

I m trying to use group by clause in left join sql query and it is not working.
Please help me out, thanks in advance.
SELECT Cust_Mst_Det.Cust_Hd_Code,
Cust_Mst_Det.First_Name,
SL_HEAD20152016.vouch_date AS invoice_2,
SL_HEAD20142015.vouch_date AS invoice_1,
Cust_Mst_Hd.EMail
FROM Cust_Mst_Det
LEFT JOIN SL_HEAD20142015 ON Cust_Mst_Det.Cust_Hd_Code=SL_HEAD20142015.Member_Code
LEFT JOIN SL_HEAD20152016 ON Cust_Mst_Det.Cust_Hd_Code=SL_HEAD20152016.Member_Code
LEFT JOIN Cust_Mst_Hd ON Cust_Mst_Det.Cust_Hd_Code=Cust_Mst_Hd.Cust_Hd_Code
WHERE cust_mst_det.first_name!='NIL'
GROUP BY Cust_Mst_Det.Cust_Hd_Code
ORDER BY SL_HEAD20152016.vouch_date DESC,
SL_HEAD20142015.vouch_date

I'm not sure which DBMS you are using, but on an Oracle your query will not work at all.
First issue: The GROUP BY statement is used in conjunction with the aggregate functions to group the result-set by one or more columns. You do not have any aggregating function in your SELECT statement (count, max, etc.)
Second issue: you must specify all columns from SELECT statement in your GROUP BY statement (excluding columns that represents results of aggregation).
As I said I don't know which DB is used by you, but those two points should be applicable for the most of SQL standards.

It appears that it is impossible to use an ORDER BY on a GROUP BY summarisation. My fundamental logic is flawed. I will need to run the following subquery.
ex :
SELECT p.*, pp.price
FROM products p
LEFT JOIN ( SELECT price FROM product_price ORDER BY date_updated DESC ) pp
ON p.product_id = pp.product_id GROUP BY p.product_id;
This will take a performance hit but as it is the same subquery for each row it shouldn't be too bad.

Related

NTILE Function and Using Inner Join in Oracle

I am supposed to use the given Database(Its pretty huge so I used codeshare) to list last names and customer numbers of top 5% of customers for each branch. To find the top 5% of customers, I decided to use the NTILE Function, (100/5 = 20, hence NTILE 20). The columns are pulled from two separate tables so I used Inner joins. For the life of me, I honesly cannot figure out where I am going wrong. I keep getting "missing expression" errors but Do not know what exactly I am missing. Here is the Database
Database: https://codeshare.io/5XKKBj
ERD: https://drive.google.com/file/d/0Bzum6VJXi9lUX1d2ZkhudTE3QXc/view?usp=sharing
Here is my SQL Query so far.
SELECT
Ntile(20) over
(partition by Employee.Branch_no
order by sum(ORDERS.SUBTOTAL) desc
) As Top_5,
CUSTOMER.CUSTOMER_NO,
CUSTOMER.LNAME
FROM
CUSTOMER
INNER JOIN ORDERS
ON
CUSTOMER.CUSTOMER_NO = ORDERS.CUSTOMER_NO
GROUP BY
ORDERS.SUBTOTAL,
CUSTOMER.CUSTOMER_NO,
CUSTOMER.LNAME;
You need to join Employee and the GROUP BY must include all non-aggregated expressions. You can use a subquery to generate the subtotals and get the NTILE in the outer query, e.g.:
SELECT
Ntile(20) over
(partition by BRANCH_NO
order by sum_subtotal desc
) As Top_5,
CUSTOMER_NO,
LNAME
FROM (
SELECT
EMPLOYEE.BRANCH_NO,
CUSTOMER.CUSTOMER_NO,
CUSTOMER.LNAME,
sum(ORDERS.SUBTOTAL) as sum_subtotal
FROM CUSTOMER
JOIN ORDERS
ON CUSTOMER.CUSTOMER_NO = ORDERS.CUSTOMER_NO
JOIN EMPLOYEE
ON ORDERS.EMPLOYEE_NO = EMPLOYEE.EMPLOYEE_NO
GROUP BY
EMPLOYEE.BRANCH_NO,
CUSTOMER.CUSTOMER_NO,
CUSTOMER.LNAME
);
Note: you might want to include BRANCH_NO in the select list as well, otherwise the output will look confusing with duplicate customers (if a customer has ordered from employees in multiple branches).
Now, if you want to filter the above query to just get the top 5%, you can put the whole thing in another subquery and add a predicate on the Top_5 column, e.g.:
SELECT CUSTOMER_NO, LNAME
FROM (... the query above...)
WHERE Top_5 = 1;

Is it possible to use AND with three tables and using left join/inner join

I am in need of a very strange problem. I hope you brilliant guys will enjoy this problem (or may be it's an easy task for you :) ).
Here is the query I am using to return values from three tables
select listing.*
, sum(review.rNumber) as nor
, count(review.rNumber) as total
, users.username from listing
where
left join review on listing.lid=review.lID
inner join users on users.uid=listing.cuid
group by listing.lid
Now in this query I want to use an additional filter. It is returning all the values from listing table but I want to return all values using WHERE cat='Hair' or something
I don't have any idea how to insert where clues in this query.. Please let me know if it doable.
Thanks
If you want the filter to apply before the group by:
select listing.*, sum(review.rNumber) as nor, count(review.rNumber) as total, users.username from listing
left join review on listing.lid=review.lID
inner join users on users.uid=listing.cuid
where cat='Hair'
group by listing.lid
If you want it after, you use "having" instead:
select listing.*, sum(review.rNumber) as nor, count(review.rNumber) as total, users.username from listing
left join review on listing.lid=review.lID
inner join users on users.uid=listing.cuid
group by listing.lid
having cat='Hair'
Your query should be as follow.
select listing.lid
, sum(review.rNumber) as nor
, count(review.rNumber) as total
, users.username from listing
left join review on listing.lid=review.lID
inner join users on users.uid=listing.cuid
where
cat='Hair
group by listing.lid,users.username
First of all, you need to follow
Select
From
Where
Group By
Second, if you use group by, you may not select any column that is not in aggregate function or in group by. Therefore, listing.* can not be done. If you need that values, put them in the both group by and select.

Oracle SQL sum transactions by distinct customer id

I need to select the sum of transaction columns, count # of transactions, all by distinct customer ids. I have tried a few nested queries as well as something like the following:
select distinct(customer_id), sum(tran_amt), count(tran)
from tran_table
inner join tender_table;
The tender_table has the customer id so I have to join it.
You are using group functions, but you don't have a "group by" clause, I think this will give you the correct answer:
SELECT customer_id, SUM(tran_amt), COUNT(tran)
FROM tran_table INNER JOIN tender_table
GROUP BY CUSTOMER_ID;
I am guessing you want something like this:
select te.customer_id, sum(t.tran_amt), count(*)
from tran_table t inner join
tender_table te
on t.?? = te.??
group by te.customer_id;
You need join conditions and a group by clause. The ?? is for the columns used for the join, which your question does not specify.
Try this :
select tb_tran.customer_id, sum(tran_amt), count(tran)
from tran_table tb_tran inner join tender_table tb_tender
on tb_tran.customer_id = tb_tender.customer_id
group by tb_tran.customer_id;

How to find the most frequent value in a select statement as a subquery?

I am trying to get the most frequent Zip_Code for the Location ID from table B. Table A(transaction) has one A.zip_code per Transaction but table B(Location) has multiple Zip_code for one area or City. I am trying to get the most frequent B.Zip_Code for the Account using Location_D that is present in both table.I have simplified my code and changed the names of the columns for easy understanding but this is the logic for my query I have so far.Any help would be appreciated. Thanks in advance.
Select
A.Account_Number,
A.Utility_Type,
A.Sum(usage),
A.Sum(Cost),
A.Zip_Code,
( select B.zip_Code from B where A.Location_ID= B.Location_ID having count(*)= max(count(B.Zip_Code)) as Location_Zip_Code,
A.Transaction_Date
From
Transaction_Table as A Left Join
Location Table as B On A.Location_ID= B.Location_ID
Group By
A.Account_Number,
A.Utility_Type,
A.Zip_Code,
A.Transaction_Date
This is what I come up with:
Select tt.Account_Number, tt.Utility_Type, Sum(tt.usage), Sum(tt.Cost),
tt.Zip_Code,
(select TOP 1 l.zip_Code
Location_Table l
where tt.Location_ID = l.Location_ID
group by l.zip_code
order by count(*) desc
) as Location_Zip_Code,
tt.Transaction_Date
From Transaction_Table tt
Group By tt.Account_Number, tt.Utility_Type, tt.Zip_Code, tt.Transaction_Date;
Notes:
Table aliases are a good thing. However, they should be abbreviations for the tables referenced, rather than arbitrary letters.
The table alias qualifies the column name, not the function. Hence sum(tt.usage) rather than tt.sum(usage).
There is no need for a join in the outer query. You are doing all the work in the subquery.
An order by with top seems the way to go to get the most common zip code (which, incidentally, is called the mode in statistics).

AS being ignored in a subquery

Still learning SQL here... I have part of a subquery:
(Select MAX(cost) AS Cost_of_Car FROM Car_Purchase)
But it does not take my label just uses the one from the table, in this case "cost"
Any ideas?
EDIT: Just realized I could in my SELECT statement call out AS "NAME OF COLUMN", but why does it not accept AS in the subquery?
POSTING FULL QUERY
SELECT CAR.name, Car_Purchase.cost_per_night, Car_Purchase.description
FROM Car_Purchase
JOIN CAR ON Car_Purchase.purchase_id = CAR.purchase_id
GROUP BY CAR.name, Car_Purchase.cost_per_night, Car_Purchase.description
HAVING Car_Purchase.cost = (SELECT MAX(cost) AS Cost_of_Car FROM Car_Purchase)
The AS keyword is not being ignored.
You're using subquery in where clause. Remember, where clause is used for filtering the query result, not for displaying the data.
If you want to see how AS work in subquery, try this:
SELECT CAR.name, Car_Purchase.cost_per_night, Car_Purchase.description, Cost_of_Car
FROM Car_Purchase
JOIN CAR ON Car_Purchase.purchase_id = CAR.purchase_id
join (SELECT MAX(cost) AS Cost_of_Car FROM Car_Purchase) subquery
ON Car_Purchase.cost = subquery.Cost_of_Car
GROUP BY CAR.name, Car_Purchase.cost_per_night, Car_Purchase.description
In this query, I put the subquery in from clause. So your query result now have Cost_of_Car column and you can display it in select clause.
In fact, since, as noted by others the Max(Cost) is not being used elsewhere in the query, you don't need to alias it at all. And since you don't have a aggregate function anywhere in the sql it does not need to be a group By query
Select cp.name, cp.Cost CostOfCar,
cp.cost_per_night, cp.description
From Car_Purchase cp Join Car c
On c.purchase_id = cp.purchase_id
Where cp.cost = (SELECT MAX(cost) FROM Car_Purchase)
Is sufficient and should work