sql join and count error - sql

I am trying to count how many employees there are at certain stores and group by store code from 2 tables containing, 1-Emplyee.EMP_CODE,STORE_CODE Table and 2-STORE.store_code...
(STORE tbl-does not contain EMP_CODE) SO I may not even be on the right track.
SELECT c.EMP_CODE,c.STORE_CODE,s.STORE_CODE,COUNT(c.EMP_CODE)
FROM EMPLOYEE c
LEFT OUTER JOIN STORE s
on c.STORE_CODE=s.STORE_CODE
GROUP BY s.STORE_CODE
;
Keep Getting an error:
Msg 8120, Level 16, State 1, Line 1 Column 'EMPLOYEE.EMP_CODE' is
invalid in the select list because it is not contained in either an
aggregate function or the GROUP BY clause.

As the error states, you need to have all non-aggregate columns in your GROUP BY, from those that you are selecting.
Option 1: Add all of the non-aggregate columns to your GROUP BY
SELECT c.EMP_CODE,c.STORE_CODE,s.STORE_CODE,COUNT(c.EMP_CODE)
FROM EMPLOYEE c
LEFT OUTER JOIN STORE s
on c.STORE_CODE=s.STORE_CODE
GROUP BY c.EMP_CODE,c.STORE_CODE,s.STORE_CODE;
Option 2: Remove all non-grouped columns from your original SELECT
SELECT s.STORE_CODE, COUNT(c.EMP_CODE)
FROM EMPLOYEE c
LEFT OUTER JOIN STORE s
on c.STORE_CODE=s.STORE_CODE
GROUP BY s.STORE_CODE;
Option 3: Use a nested select to COUNT(c.EMP_CODE) and only GROUP BY s.STORE_CODE, while still being able to select all of the columns you want. Something like:
SELECT c.EMP_CODE,c.STORE_CODE,s.STORE_CODE,A.Count_Emp
FROM EMPLOYEE c
LEFT OUTER JOIN STORE s
on c.STORE_CODE=s.STORE_CODE
LEFT OUTER JOIN (
SELECT s.STORE_CODE, COUNT(c.EMP_CODE) as 'Count_Emp'
FROM EMPLOYEE c
LEFT OUTER JOIN STORE s
ON c.STORE_CODE=s.STORE_CODE
GROUP BY s.STORE_CODE
) A on A.STORE_CODE = c.STORE_CODE;

You are missing all the columns from your GROUP BY Clause. That should fix it!

Related

PostgreSQL GROUP BY column must appear in the GROUP BY

SELECT
COUNT(follow."FK_accountId"),
score.*
FROM
(
SELECT items.*, AVG(reviews.score) as "averageScore" FROM "ITEM_VARIATION" as items
INNER JOIN "ITEM_REVIEW" as reviews ON reviews."FK_itemId"=items.id
GROUP BY items.id
) as score
INNER JOIN "ITEM_FOLLOWER" as follow ON score.id=follow."FK_itemId"
GROUP BY score.id
Inner Block works by itself and I believe I followed the same format.
However it outputs error:
ERROR: column "score.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 18: score.*
^
Is listing all the columns in score field only solution?
there are over 10 columns to list so I'd like to avoid that solution if it's not the only one
columns not included on the aggregation must be specified during group by
SELECT
COUNT(follow."FK_accountId"),
score.id,
score.name
FROM
(
SELECT items.id as id, items.name as name, AVG(reviews.score) as "averageScore" FROM "ITEM_VARIATION" as items
INNER JOIN "ITEM_REVIEW" as reviews ON reviews."FK_itemId"=items.id
GROUP BY items.id, items.name
) as score
INNER JOIN "ITEM_FOLLOWER" as follow ON score.id=follow."FK_itemId"
GROUP BY score.id, score.name
I would suggest you use correlated subqueries or a lateral join:
SELECT i.*,
(SELECT AVG(r.score)
FROM "ITEM_REVIEW" r
WHERE r."FK_itemId" = i.id
) as averageScore,
(SELECT COUNT(*)
FROM "ITEM_FOLLOWER" f
WHERE f."FK_itemId" = i.id
)
FROM "ITEM_VARIATION" i;
With the right indexes, this is probably faster as well.

SQL tables joined with max

I'm working with two tables. I have a full list of groups in table A, and a list of each group member that has been reviewed in table B. So table B is a log of all review records for those members for each group.
select a.Group_Name, Max(b.Request_Review_Date)
From GroupTable a
Left Outer Join GroupReviews b ON a.Group_Name = b.Group_Name
Group By a.Group_Name
What I am trying to return is the full list of groups from table A, and find the latest review date from table B for each of those groups.
I have researched and tried all or most of the inner & outer joins, apply methods....but its just not giving me the results. Can anyone point me in the right direction? Or am I having to bring back two result sets and compare in my ASP code-behind?
Try a CTE then join back to it
WITH Recent AS
(
select group_name, max(Request_Review_Date) AS 'MaxReviewDate'
from GroupReviews
group by group_name
)
select a.group_name, MaxReviewDate
from GroupTable a left join Recent
on group_name = a.group_name
if you need the value for max for all the a.group name rows the ypu should join the subquery for max date
select a.Group_Name, t.max_date
left join (
select b.Group_Name, Max(b.Request_Review_Date) max_date
from GroupReviews b
Group By b.Group_Name
) t on t.Group_Name = a.Group_Name

How to solve the SQL error: "Every derived table must have its own alias" in case of joins

I am using this query:
select max(counted)
from (select max(outcome.player_of_match) counted
from outcome
inner join player
on player.id=outcome.player_of_match group by player.id);
It shows the SQL error:
Every derived table must have its own alias.
You just need to add an alias to the subquery you're selecting from:
select max(T1.counted)
from (
select max(outcome.player_of_match) counted
from outcome
inner join player
on player.id=outcome.player_of_match
group by player.id
) AS T1;

How to use WITH clause and select clause

click here to view screenshot of table
Question: write a query to display the customer number, firstname, lastname for those client where total loan amount taken is maximum and at least taken from 2 bank branch.
I have tried the following query but I'm getting this error
Msg 8120, Level 16, State 1, Line 7
Column 'customer.fname' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Code:
with l as
(
select custid, sum(loan_amount) as tot
from loan
group by custid
having count(bid) >= 2
)
select
concat(c.fname, c.ltname) as name,
max(l.tot)
from
customer as c, l
where
l.custid = c.custid
You need to have a GROUP BY to select both aggregated and non-aggregated data, so you need to decide how you want the data grouped. You could do either
SELECT CONCAT(c.fname,c.ltname) as name, MAX(l.tot)
FROM customer AS c
INNER JOIN l ON l.custid=c.custid
GROUP BY c.fname,c.ltname
or
SELECT CONCAT(c.fname,c.ltname) as name, MAX(l.tot)
FROM customer AS c
INNER JOIN l ON l.custid=c.custid
GROUP BY concat(c.fname,c.ltname)
Please note the following:
I converted the "old" join syntax to the more acceptable INNER JOIN syntax
You probably want a space between the first and late name if you're displaying the results.

How to list unused items from database

MDW_CUSTOMER_ACCOUNTS has the following fields: ACCOUNT_ID, MEAL_ID.
MDW_MEALS_MENU has the following fields: MEAL_ID, MEAL_NAME.
I am trying to generate a report on the number of times a particular meal has been subscribed to by a customer using the query,
SELECT count(a.account_id), b.meal_id, b.meal_name
FROM mdw_meals_menu b LEFT JOIN mdw_customer_accounts a
on b.meal_id=a.meal_id
WHERE
a.start_date BETWEEN to_date('01-APR-2013','DD-MON-YYYY')
AND to_date('30-JUN-2013','DD-MON-YYYY')
GROUP BY b.meal_id, b.meal_name
ORDER BY count(a.account_id) desc, b.meal_id;
This only lists the MEAL_IDs that has been subscribed to at least once. But it is not displaying the Ids that have not been subscribed to.
How do I get these MEAL_IDs to print with the count being 0?
i have modified the code, but still i get the same result.
Your where clause is effectively turning your outer join back into an inner join - conditions on an outer-joined table should generally be in the join clause, like so:
SELECT count(a.account_id), b.meal_id, b.meal_name
FROM mdw_meals_menu b
LEFT JOIN mdw_customer_accounts a
on b.meal_id=a.meal_id and
a.start_date BETWEEN to_date('01-APR-2013','DD-MON-YYYY')
AND to_date('30-JUN-2013','DD-MON-YYYY')
GROUP BY b.meal_id, b.meal_name
ORDER BY count(a.account_id) desc, b.meal_id;
You should use a left outer join .