how to get count of a column along with column from another table - sql

is there any other way for this problem .I wanted to use group by cant use ii.
my solution:
SQL> select (select count(dr_id)
from cus_detail c
where c.dr_id=d.dr_id) as count_cus,dr_name from driver_detail d;
COUNT_CUS DR_NAME
---------- ---------------
1 raju
0 mandi
2 sajuman
3 babu ram coi
0 daju
0 bare babu

use this one.
select count(c.dr_id) as count_cus, d.dr_name
from driver_detail d
inner join cus_detail c on c.dr_id=d.dr_id
group by d.dr_name

I'm not totally sure I understand what you're asking but I think you're asking how to group things and bring in data from another table
I typically prefer to do this as a grouping subquery:
select
d.dr_name,
c.ctr
from
(select dr_id, count(dr_id) ctr from cus_detail group by dr_id) c
INNER JOIN driver_detail d ON c.dr_id=d.dr_id
The reason why here is that by grouping on the id when counting means we can keep a count for two different people (i.e. different id) both called John. If instead we joined on id then grouped on the Name then two different people both called John would have their counts added together
It's also good to group and count in a subquery because sometimes grouping and counting in the outer query introduces wrong counts if three or more tables are related in 1:Many fashion. If a record in a had 3 records in b and 4 records in c, and we join all before we count we will count 12 records. If we group first we will be joining in 1:1 relationship instead and the counter won't inflate erroneously

If two DR_NAME are same then GROUP BY can give different result then what your current query will give.
So better to use an analytical function as the following:
SELECT
COUNT(C.DR_ID) OVER(
PARTITION BY C.DR_ID
) AS COUNT_CUS,
DR_NAME
FROM
DRIVER_DETAIL D
JOIN CUS_DETAIL C ON ( C.DR_ID = D.DR_ID )
Cheers!!

I think you want a basic aggregation query. Your method is correct (although it could be formatted better). The more standard method is join/group by:
select d.dr_name, count(c.dr_id)
from driver_detail d left join
cus_detail c
on c.dr_id = d.dr_id
group by d.dr_name;

Related

Issue using HAVING-Clause: Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause) [duplicate]

I am using Firebird SQL. The below mentioned query returns 4 rows as shown in the figure.
SELECT a.EPS_ID,b.C_NAME,c.AY_YR_NAME,d.S_NAME,e.E_NAME
FROM
TBLEXAMPLANNER_S_MSB a,
TBLCLASS_MSB b,
TBLACADEMICYEAR_MSB c,
TBLSUBJECTS_MSB d,
TBLEXAMTYPE_MSB e
WHERE
a.EPS_CLASS_ID=b.C_ID
AND a.EPS_SESSION_ID=c.AY_ID
AND a.EPS_SUB_ID=d.S_ID
AND a.EPS_PE_ID=e.E_ID
I want it to return only 1(one) row like
EPS_ID C_NAME AY_YR_NAME S_NAME E_NAME
---------------------------------------------------
7 5 2016-2017 English FA1
I am using the following query but it does not work.
SELECT a.EPS_ID,MAX(b.C_NAME) AS XT,c.AY_YR_NAME,d.S_NAME,e.E_NAME
FROM
TBLEXAMPLANNER_S_MSB a,
TBLCLASS_MSB b,
TBLACADEMICYEAR_MSB c,
TBLSUBJECTS_MSB d,
TBLEXAMTYPE_MSB e
WHERE
a.EPS_CLASS_ID=b.C_ID
AND a.EPS_SESSION_ID=c.AY_ID
AND a.EPS_SUB_ID=d.S_ID
AND a.EPS_PE_ID=e.E_ID
GROUP BY a.EPS_ID,d.S_NAME
The error message is :
Invalid expression in the select list (not contained in either an
aggregate function or the GROUP BY clause)
The usage of GROUP BY makes the engine group the records for you. To do grouping, you have to give advice to the RDBMS for each column, what it should do.
Group it? -> Add column to GROUP BY-Clause
Not group it? -> ok, what else?
ignore the column? remove it from your select-clause
Sum it? -> use SUM(mycol)
other aggregation functions can be found in the documentation
Additionally: In your case you try to group by EPS_ID, which is unique in each row. So a grouping by that column will return all rows, because there is nothing to group by. To group records, they have to have the same value.
Learn to use proper, explicit JOIN syntax.
Your problem is that all unaggregated columns need to be in the GROUP BY:
SELECT a.EPS_ID, MAX(b.C_NAME) AS XT, c.AY_YR_NAME, d.S_NAME, e.E_NAME
FROM TBLEXAMPLANNER_S_MSB a JOIN
TBLCLASS_MSB b
ON a.EPS_CLASS_ID = b.C_ID JOIN
TBLACADEMICYEAR_MSB c
ON a.EPS_SESSION_ID = c.AY_ID JOIN
TBLSUBJECTS_MSB d
ON a.EPS_SUB_ID = d.S_ID JOIN
TBLEXAMTYPE_MSB e
ON a.EPS_PE_ID = e.E_ID
GROUP BY a.EPS_ID, c.AY_YR_NAME, d.S_NAME, e.E_NAME;
Note: I would also recommend that you use table abbreviations for table aliases. So, ep for TBLEXAMPLANNER_S_MSB instead of a. Arbitrary table aliases make the query hard to follow.
Try
SELECT a.EPS_ID,c.AY_YR_NAME,d.S_NAME,e.E_NAME,MAX(b.C_NAME) AS XT ...
GROUP BY 1,2,3,4

COUNT is outputting more than one row

I am having a problem with my SQL query using the count function.
When I don't have an inner join, it counts 55 rows. When I add the inner join into my query, it adds a lot to it. It suddenly became 102 rows.
Here is my SQL Query:
SELECT COUNT([fmsStage].[dbo].[File].[FILENUMBER])
FROM [fmsStage].[dbo].[File]
INNER JOIN [fmsStage].[dbo].[Container]
ON [fmsStage].[dbo].[File].[FILENUMBER] = [fmsStage].[dbo].[Container].[FILENUMBER]
WHERE [fmsStage].[dbo].[File].[RELATIONCODE] = 'SHIP02'
AND [fmsStage].[dbo].[Container].DELIVERYDATE BETWEEN '2016-10-06' AND '2016-10-08'
GROUP BY [fmsStage].[dbo].[File].[FILENUMBER]
Also, I have to do TOP 1 at the SELECT statement because it returns 51 rows with random numbers inside of them. (They are probably not random, but I can't figure out what they are.)
What do I have to do to make it just count the rows from [fmsStage].[dbo].[file].[FILENUMBER]?
First, your query would be much clearer like this:
SELECT COUNT(f.[FILENUMBER])
FROM [fmsStage].[dbo].[File] f INNER JOIN
[fmsStage].[dbo].[Container] c
ON v.[FILENUMBER] = c.[FILENUMBER]
WHERE f.[RELATIONCODE] = 'SHIP02' AND
c.DELIVERYDATE BETWEEN '2016-10-06' AND '2016-10-08';
No GROUP BY is necessary. Otherwise you'll just one row per file number, which doesn't seem as useful as the overall count.
Note: You might want COUNT(DISTINCT f.[FILENUMBER]). Your question doesn't provide enough information to make a judgement.
Just remove GROUP BY Clause
SELECT COUNT([fmsStage].[dbo].[File].[FILENUMBER])
FROM [fmsStage].[dbo].[File]
INNER JOIN [fmsStage].[dbo].[Container]
ON [fmsStage].[dbo].[File].[FILENUMBER] = [fmsStage].[dbo].[Container].[FILENUMBER]
WHERE [fmsStage].[dbo].[File].[RELATIONCODE] = 'SHIP02'
AND [fmsStage].[dbo].[Container].DELIVERYDATE BETWEEN '2016-10-06' AND '2016-10-08'

MS Access SQL left join giving all 0

I am trying to make a summary table of all the items I have. I have a raw data table with 10 users who respectively have different items. There are maximum 3 different items and I want to do a count to see how many items each individual has. The following is my code.
Select b.Country,b.UserID,Num_including_fruits, Apple,Orange
from
(((SELECT o.Country,o.UserID, IIF(ISNULL(Count(o.UserID)),0,Count(o.UserID))
AS Num_including_fruits
FROM [SEA2_View] as o
GROUP BY o.UserID, o.Country
ORDER BY Country)as b
LEFT JOIN
(SELECT o.Country,o.UserID,IIF(ISNULL(Count(o.UserID)),0,Count(o.UserID)
AS Apple
FROM [APAC2_View] as o
WHERE o.fruit_status <>"fresh" AND o.HWType = "Apple"
GROUP BY o.Country,o.UserID)as d
ON (b.UserID = d.UserID))
LEFT JOIN
(SELECT o.Country,o.UserID,IIF(ISNULL(Count(o.UserID)),0,Count(o.UserID))
AS Orange
FROM [SEA2_View] as o
WHERE o.fruit_status <>"fresh" AND o.HWType = "Orange"
GROUP BY o.Country,o.UserID)as e
ON (d.UserID = e.UserID))
;
The first join returns the correct result but the second join somehow returns all 0, which is incorrect. Therefore please help! and I would appreciate any advice for best practice when it comes to joins in SQL. Thanks lot!
Are you sure you don't have a table naming error?
You're first joining [SEA2_View] with [APAC2_View]. The second join is joining with [SEA2_View] with itself.

How to solve this query

i have to two tables in sql:
tbl_Rooms(Room_Id, Room_Beds);
tbl_AllocatedRooms(Room_Id, Bed_No);
i want to get the result as:
1: List of all the rooms in which no bed is allocated.
2: List of rooms in which one or more beds are allocated also the number of remaining beds(for example if i have a room_id = 2 in tbl_Rooms with Beds = 5 and 2 of these beds are allocated i want to get the remaining number of beds)
i have done the first one but cant figure how to get the second one.
Here is my query for the first one:
SELECT * INTO #tempUnAllocated FROM tbl_Rooms WHERE Room_Id NOT IN
(SELECT Room_Id FROM tbl_Allocation);
SELECT A.room_id,A.room_beds,count(B.bed_no) as allocated_beds,
(A.room_beds - count(B.bed_no)) as remaining_beds
from tbl_rooms A LEFT JOIN tbl_AllocatedRooms B
ON A.room_id = B.room_id
group by A.room_id,A.room_beds
having allocated_beds < room_beds
You can refer the solution here.
This should do it, although a solution using a CTE might be more readable, if your RDBMS supports them.
SELECT a.Room_Id, (SELECT Room_Beds FROM tbl_Rooms r WHERE r.Room_Id=a.Room_Id)-COUNT(*) AS unallocatedBeds
FROM tbl_allocatedRooms a
GROUP BY a.Room_Id

SQL select from two tables, using a distinct value between the two IF it exists, otherwise only using value from the first table?

I have two tables, with structures like this:
roomlist:
-room (unique)
-totalDesks
userlist:
-room (has duplicates)
-deskOwned
I need a SQL statement that will spit out the following:
room
totalDesks
desksUsed (COUNT(DISTINCT userlist.desk))
desksOpen (totalDesks-(COUNT(DISTINCT userlist.desk)))
I have this so far:
SELECT
DISTINCT roomList.room, userlist.room, roomList.totalDesks,
COUNT(DISTINCT userlist.desk) AS desksUsed,
roomlist.totalDesks - COUNT(DISTINCT userlist.desk) AS desksOpen
FROM
roomlist, userlist
WHERE
roomlist.room = userlist.room
The problem is that not all rooms currently have users in them. If I have rooms A, B, C and D, but only records of people in A, B and C, it won't include room D in the result - even though room D has 5 totalDesks, none of which are taken.
How can I get a result that will still give me results on a room from roomlist, even if no records exist for that room in userlist?
Try a LEFT JOIN instead. I assume you need to group by room as well:
SELECT DISTINCT
roomList.room,
userlist.room,
roomList.totalDesks,
COUNT(DISTINCT userlist.desk) AS desksUsed,
roomlist.totalDesks-COUNT(DISTINCT userlist.desk) AS desksOpen
FROM roomlist
LEFT JOIN userlist ON roomlist.room=userlist.room
GROUP BY roomList.room,
userlist.room,
roomList.totalDesks
I would suggest mocking this up in http://sqlfiddle.com/ it will be much easier to help you then