SQL Query: How do you combine count function result into a select query? - sql

select distinct Franchise.FranchiseName, Franchise.Initials, Franchise.StoreNo, AccountCancellation_Process.Store_Num
FROM FranchiseData
INNER JOIN AccountCancellation_Process
on FranchiseData.StoreNo = AccountCancellation_Process.Store_Num
select count(*) from AccountCancellation_Process where Store_Num = '1234'
select count(*) from AccountCancellation_Process where Store_Num = '1234' and Progress is not null
I want to combine the count(*) from AccountCancellation_Process into the above inner join statement so the query will give me the result of FranchiseName, Initials, StoreNo from Franchise table and Store_Num from the AccountCancellation_Process with the total records and total record with Progress column not null.
how do you combine the query result with count function result?
thank.

Like this I think is what you want.
I created two table value correlated subqueries to get the data based on the stored number in the inner join table. Then I join them based on the store number. That way the distinct will work. But you might also be able to do the counts in the select part with using just correlated subqueries. I was worried the distinct might not work though.
SELECT DISTINCT Franchise.FranchiseName, Franchise.Initials, Franchise.StoreNo, acp.Store_Num, total_count.Total_Count, progress_count.Progress_Count
FROM FranchiseData
INNER JOIN AccountCancellation_Process AS acp ON (FranchiseData.StoreNo = acp.Store_Num)
INNER JOIN (SELECT Store_Num, COUNT(*) AS Total_Count FROM AccountCancellation_Process WHERE Store_Num = acp.Store_Num) AS total_count ON (acp.Store_Num = total_count.Store_Num)
INNER JOIN (SELECT Store_Num, COUNT(*) AS Progress_Count FROM AccountCancellation_Process WHERE Store_Num = acp.Store_Num AND Progress IS NOT NULL) AS progress_count ON (acp.Store_Num = progress_count.Store_Num)

Alias the count(*) then use a Sum(alias)

Related

SQL dividing a count from one table by a number from a different table

I am struggling with taking a Count() from one table and dividing it by a correlating number from a different table in Microsoft SQL Server.
Here is a fictional example of what I'm trying to do
Lets say I have a table of orders. One column in there is states.
I have a second table that has a column for states, and second column for each states population.
I'd like to find the order per population for each sate, but I have struggled to get my query right.
Here is what I have so far:
SELECT Orders.State, Count(*)/
(SELECT StatePopulations.Population FROM Orders INNER JOIN StatePopulations
on Orders.State = StatePopulations.State
WHERE Orders.state = StatePopulations.State )
FROM Orders INNER JOIN StatePopulations
ON Orders.state = StatePopulations.State
GROUP BY Orders.state
So far I'm contending with an error that says my sub query is returning multiple results for each state, but I'm newer to SQL and don't know how to overcome it.
If you really want a correlated sub-query, then this should do it...
(You don't need to join both table in either the inner or outer query, the correlation in the inner query's where clause does the 'join'.)
SELECT
Orders.state,
COUNT(*) / (SELECT population FROM StatePopulation WHERE state = Orders.state)
FROM
Orders
GROUP BY
Orders.state
Personally, I'd just join them and use MAX()...
SELECT
Orders.state,
COUNT(*) / MAX(StatePopulation.population)
FROM
Orders
INNER JOIN
StatePopulation
StatePopulation.state = Orders.state
GROUP BY
Orders.state
Or aggregate your orders before you join...
SELECT
Orders.state,
Orders.order_count / StatePopulation.population
FROM
(
SELECT
Orders.state,
COUNT(*) AS order_count
FROM
Orders
GROUP BY
Orders.state
)
Orders
INNER JOIN
StatePopulation
StatePopulation.state = Orders.state
(Please forgive typos and smelling pistakes, I'm doing this on a phone.)

Inner join in my query seems to not be recognized

I have a little question about a problem with a SQL query. I've written a query to get some records and the number of occurences of those records. The problem is that I'd like to join two tables so I can get some values instead of foreign keys. This is my actual query (which I think is wrong because there is no joins in the result) :
SELECT date, heure_debut, heure_fin, Event_id,
horaire_id, local_id, enseignant_id, COUNT(*) doublons
FROM `reservations`
INNER JOIN `events` ON `events`.`id` = `reservations`.`Event_id`
INNER JOIN `couleurs` ON `couleurs`.`id` = `events`.`couleur_id`
GROUP BY date,
heure_debut,
heure_fin,
Event_id,
horaire_id,
local_id,
enseignant_id
HAVING COUNT(*) > 1 OR COUNT(*) = 1
Thank you for your answers.
Sort of a wild guess based on the OP's description of his intent.
Assuming that table events has a column titre that is an AK, the following modifications to the original query might mirror this intent. Instead of the event id it shows its name:
SELECT date, heure_debut, heure_fin, `events`.titre,
horaire_id, local_id, enseignant_id, COUNT(*) doublons
FROM `reservations`
INNER JOIN `events` ON `events`.`id` = `reservations`.`Event_id`
INNER JOIN `couleurs` ON `couleurs`.`id` = `events`.`couleur_id`
GROUP BY date,
heure_debut,
heure_fin,
`events`.titre,
horaire_id,
local_id,
enseignant_id
HAVING COUNT(*) > 0
;

Query all columns of table1 left join and count of the table2

I couldn't get this query working :
DOESN'T WORK
select
Region.*, count(secteur.*) count
from
Region
left join
secteur on secteur.region_id = Region.id
The solution I found is this but is there a better solution using joins or if this doesn't affect performance, because I have a very large dataset of about 500K rows
WORKS BUT AFRAID OF PERFORMANCE ISSUES
select
Region.*,
(select count(*)
from Secteur
where Secteur.Region_id = region.id) count
from
Region
I would suggest:
select region.*, count(secteur.region_id) as count
from region left join secteur on region.id = secteur.region_id
group by region.id, region.field2, region.field3....
Note that count(table.field) will ignore nulls, whereas count(*) will include them.
Alternatively, left join on a subquery and use coalesce to avoid nulls:
select region.*, coalesce(t.c, 0) as count
from region left join
(select region_id, count(*) as c from secteur group by region_id) t on region.id = t.region_id
I'd join region on an aggregate query of secteur:
SELECT r.*, COALESCE(s.cnt, 0)
FROM region r
LEFT JOIN (SELECT region_id, COUNT(*) AS cnt
FROM secteur
GROUP BY region_id) s ON s.region_id = r.id
I would go with this query:
select r.*,
(select count(*)
from Secteur s
where s.Region_id = r.id
) as num_secteurs
from Region r;
Then fix the performance problem by adding an index on Secteur(region_id):
create index idx_secteur_region on secteur(region_id);
You make a two mistakes
First: you have try to calulate COUNT() in only one (I mean, the second) table. This doesn't will work because theCOUNT(), like an any aggregate function, calculates only for the whole set of rows, not just for any part of the set (not only just for the one or an other joined table).
In your first query, you may replace secteur. * only by asterisk, like a Region.region_id, count(*) AS count, and do not forget add Region.region_id on the GROUP BY step.
Second: You has define not only aggregate function in the query, but and other fields: select Region.*, but you don't define them in GROUP BY step. You need to add to GROUP BY statement all columns, which you has define in the SELECT step but not apply an aggregate functions to them.
Append: not, GROUP BY Region.* doesn't will work, you should to define a columns in the GROUP BY step by their actual names.
So, correct form of this will looks like a
SELECT
Region.col1
,Region.col2,
, count(*) count
from Region
left join
secteur on secteur.region_id = Region.id
GROUP BY Region.col1, Region.col2
Or, if you don't want to type each name of column, use window queries
SELECT
Region.*,
, count( * ) OVER (PARTITION BY region_id) AS count
from Region
left join
secteur on secteur.region_id = Region.id

SUM a column count from two tables

I have this simple unioned query in SQL Server 2014 where I am getting counts of rows from each table, and then trying to add a TOTAL row at the bottom that will SUM the counts from both tables. I believe the problem is the LEFT OUTER JOIN on the last union seems to be only summing the totals from the first table
SELECT A.TEST_CODE, B.DIVISION, COUNT(*)
FROM ALL_USERS B, SIGMA_TEST A
WHERE B.DOMID = A.DOMID
GROUP BY A.TEST_CODE, B.DIVISION
UNION
SELECT E.TEST_CODE, F.DIVISION, COUNT(*)
FROM BETA_TEST E, ALL_USERS F
WHERE E.DOMID = F.DOMID
GROUP BY E.TEST_CODE, F.DIVISION
UNION
SELECT 'TOTAL', '', COUNT(*)
FROM (SIGMA_TEST A LEFT OUTER JOIN BETA_TEST E ON A.DOMID
= E.DOMID )
Here is a sample of the results I am getting:
I would expect the TOTAL row to display a result of 6 (2+1+3=6)
I would like to avoid using a Common Table Expression (CTE) if possible. Thanks in advance!
Since you are counting users with matching DOMIDs in the first two statements, the final statement also needs to include the ALL_USERS table. The final statement should be:
SELECT 'TOTAL', '', COUNT(*)
FROM ALL_USERS G LEFT OUTER JOIN
SIGMA_TEST H ON G.DOMID = H.DOMID
LEFT OUTER JOIN BETA_TEST I ON I.DOMID = G.DOMID
WHERE (H.TEST_CODE IS NOT NULL OR I.TEST_CODE IS NOT NULL)
I would consider doing a UNION ALL first then COUNT:
SELECT COALESCE(TEST_CODE, 'TOTAL'),
DIVISION,
COUNT(*)
FROM (
SELECT A.TEST_CODE, B.DIVISION
FROM ALL_USERS B
INNER JOIN SIGMA_TEST A ON B.DOMID = A.DOMID
UNION ALL
SELECT E.TEST_CODE, F.DIVISION
FROM BETA_TEST E
INNER JOIN ALL_USERS F ON E.DOMID = F.DOMID ) AS T
GROUP BY GROUPING SETS ((TEST_CODE, DIVISION ), ())
Using GROUPING SETS you can easily get the total, so there is no need to add a third subquery.
Note: I assume you want just one count per (TEST_CODE, DIVISION). Otherwise you have to also group on the source table as well, as in #Gareth's answer.
I think you can achieve this with a single query. It seems your test tables have similar structures, so you can union them together and join to ALL_USERS, finally, you can use GROUPING SETS to get the total
SELECT ISNULL(T.TEST_CODE, 'TOTAL') AS TEST_CODE,
ISNULL(U.DIVISION, '') AS DIVISION,
COUNT(*)
FROM ALL_USERS AS U
INNER JOIN
( SELECT DOMID, TEST_CODE, 'SIGNMA' AS SOURCETABLE
FROM SIGMA_TEST
UNION ALL
SELECT DOMID, TEST_CODE, 'BETA' AS SOURCETABLE
FROM BETA_TEST
) AS T
ON T.DOMID = U.DOMID
GROUP BY GROUPING SETS ((T.TEST_CODE, U.DIVISION, T.SOURCETABLE), ());
As an aside, the implicit join syntax you are using was replaced over a quarter of a century ago in ANSI 92. It is not wrong, but there seems to be little reason to continue to use it, especially when you are mixing and matching with explicit outer joins and implicit inner joins. Anyone else that might read your SQL will certainly appreciate consistency.

Fetch rows and count them in sqlserver

I wrote a stored procedure that join three tables to fetch province title from it's table. This is my code:
BEGIN
select TbProvince.title, count(TbProvince.title) as cnt
from TbProvince
where TbProvince.provinceId IN (select TbCustomerUser.provinceId
from TbCustomerUser INNER JOIN
TbDeals
on TbCustomerUser.UserId = TbDeals.sellerUserID
where TbDeals.buyerUserID = 1
)
group by TbProvince.title
end
Description: I have three tables for deals, customers and provinces. I want to retrieve province title and the count of that for customers that were sellers.
The above code have no problem, but only return 1 as a count. The number of customers is more than one.
Can anybody help me solve my problem?
Your query is filtering the rows of TbProvince and then aggregating that table -- and only that table.
Instead, you want to join the tables together to count the customers not the provinces. The query is much simpler to write and read if you use table aliases:
select p.Title, count(*)
from TbCustomerUser cu join
TbDeals d
on cu.UserId = d.sellerUserID join
TbProvince p
on p.provinceId = cu.provinceId
where d.buyerUserID = 1
group by p.Title;
You have to perform the JOIN with customer table. If you use semi join (expressed by IN construct in your case) then you avoid duplicates that are expected in your case.
SELECT TbProvince.title,
COUNT(TbProvince.title) AS cnt
FROM TbProvince
JOIN TbCustomerUser ON TbProvince.provinceId = TbCustomerUser.provinceId
JOIN TbDeals ON TbCustomerUser.UserId = TbDeals.sellerUserID
WHERE TbDeals.buyerUserID = 1
GROUP BY TbProvince.title;
It should be as simple as:
You won't need the subselect. Just join all three tables and you'll receive your desired result.
SELECT TbProvince.title,
count(TbProvince.title) as cnt
FROM TbProvince
INNER JOIN TbCustomerUser
ON TbProvince.provinceId = TbCustomerUser.provinceId
INNER JOIN TbDeals
ON TbCustomerUser.UserId = TbDeals.sellerUserID
AND TbDeals.buyerUserID = 1
GROUP BY TbProvince.title
Why did your solution not work?
You subselect will return a "list" of provinceIDs from TbCustomerUser combinated with TbDeals with your restriction TbDeals.buyerUserID = 1.
The outer select will now return all rows from TbProvince IN this list.
But it's not returning a row for each Customer who had a deal.
That's why you have to JOIN all three tables at once.