Use count and group by in a joins table? - sql

Here is my query and I want to add the "count of SalID group by OFID" and store the result in the same table.
SELECT
T_OF.OFID,
T_OF.OFDateDPrev, T_OF.OFDateFPrev,
T_OF_User.OFUserID,
T_OF_User.SalID
INTO T_tracing
FROM T_OF
INNER JOIN T_OF_User
ON T_OF_User.OFID = T_OF.OFID
I tried this:
SELECT
T_OF.OFID,
T_OF.OFDateDPrev, T_OF.OFDateFPrev,
T_OF_User.OFUserID,
Count (SalID) FROM T_OF_User GROUP BY OFID
INTO T_tracing
FROM T_OF
INNER JOIN T_OF_User
ON T_OF_User.OFID = T_OF.OFID
But I have an error message. Any help please?

I think you want a window function:
SELECT T_OF.OFID, T_OF.OFDateDPrev, T_OF.OFDateFPrev, T_OF_User.OFUserID,
Count(SalID) OVER (PARTITION BY T_OF.OFID) as cnt
INTO T_tracing
FROM T_OF JOIN
T_OF_User
ON T_OF_User.OFID = T_OF.OFID;
You also need to give the result of the expression a name for T_Tracing.

Related

SQL add a column with COUNT(*) to my query

I need to add a column with the content of this query :
SELECT COUNT(*) FROM account_subscriptiongroups WHERE account_subscriptiongroups.active = true AND account_subscriptiongroups.user_id = account_user.id
to this query :
SELECT
account_user.id as user_id, account_user.email, account_user.first_name, account_user.last_name, account_user.phone,
account_subscriptiongroup.id as sub_group_id,
account_adminaction.description,
account_adminaction.id as admin_action_id,
account_adminaction.created_on as subscription_ended_on
FROM
account_adminaction
LEFT JOIN
account_user ON account_user.id = account_adminaction.user_id
LEFT JOIN
account_subscriptiongroup ON account_adminaction.sub_group_id = account_subscriptiongroup.id
WHERE
account_adminaction.created_on >= '2021-04-07' AND account_adminaction.created_on <= '2021-04-13' AND
((account_adminaction.description LIKE 'Arrêt de l''abonnement%') OR (account_adminaction.description LIKE 'L''utilisateur a arrêté%'))
ORDER BY
subscription_ended_on
I tried adding a LEFT JOIN like that:
LEFT JOIN
account_subscriptiongroup all_sg ON account_user.id = account_subscriptiongroup.user_id
with this line in my WHERE statement :
AND all_sg.active = true
and this line in my SELECT :
COUNT(all_sg.id)
but I get an error :
ERROR: column "account_user.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 2: account_user.id as user_id, account_user.email, account_us...
^
I don't understand how I could perform this action properly
To count something, you need to specify a group where that count applies.
So every column that you select (and is not used in an aggregate function, like COUNT or SUM), you need to mention in the GROUP BY clause.
Or to put it the other way around: the non-aggregate columns must apply to all rows that are contained in that particular COUNT.
So between the WHERE and ORDER BY clauses, add a GROUP BY clause:
GROUP BY account_user.id, account_user.email, account_user.first_name, account_user.last_name, account_user.phone,
account_subscriptiongroup.id,
account_adminaction.description,
account_adminaction.id,
account_adminaction.created_on
If, on the other hand, you want a count from a different table, you can add a sub-select:
SELECT
account_user.id as user_id, account_user.email, account_user.first_name, account_user.last_name, account_user.phone,
account_subscriptiongroup.id as sub_group_id,
account_adminaction.description,
account_adminaction.id as admin_action_id,
account_adminaction.created_on as subscription_ended_on,
(SELECT COUNT(*)
FROM account_subscriptiongroups
WHERE account_subscriptiongroups.active = true
AND account_subscriptiongroups.user_id = account_user.id) AS groupcount
FROM
account_adminaction
LEFT JOIN
account_user ON account_user.id = account_adminaction.user_id
You can left join to to a derived table that does the grouping and counting:
SELECT au.id as user_id, au.email, au.first_name, au.last_name, au.phone,
asg.id as sub_group_id,
ad.description,
ad.id as admin_action_id,
ad.created_on as subscription_ended_on,
asgc.num_groups
FROM account_adminaction ad
LEFT JOIN account_user au ON au.id = ad.user_id
LEFT JOIN account_subscriptiongroups asg on ON ad.sub_group_id = asg.id
LEFT JOIN (
SELECT user_id, count(*) as num_groups
FROM account_subscriptiongroups ag
WHERE ag.active
GROUP by user_id
) asgc on asgc.user_id = au.id
WHERE ad.created_on >= '2021-04-07'
AND ad.created_on <= '2021-04-13'
AND ((ad.description LIKE 'Arrêt de l''abonnement%') OR (ad.description LIKE 'L''utilisateur a arrêté%'))
ORDER BY subscription_ended_on
It's not entirely clear to me, what you are trying to count, but another option (most probably slower) could be to use a window function combined with a filter clause:
count(*) filter (where asg.active) over (partition by asg.user_id) as num_groups
EDIT: my answer is the same as submitted by a_horse_with_no_name
Two answers, a literal one just solving the problem you posed, and then another one questioning whether what you asked for is really what you want.
Simple answer: modify your desired query to add user_id to the Select and remove user_id from the Where clause. Now you have a table that can be left-joined to the rest of your larger query.
...
Left Join (Select user_id, count(*) as total_count
From account_subscriptiongroup
Where account_subscriptiongroups.active = true
Group By user_id) Z
On Z.user_id=account_user.id
I question whether this count is what you really want here. This counts every account_subscriptiongroup entry for all time but only the active ones. Your larger query brings back inactive as well as active records, so if your goal is to create a denominator for a percentage, you are mixing 'apples and oranges' here.
If you decide you want a total by user of the records in your query instead, then you can add one more element to your larger query without adding any more tables. Use a windowing function like this:
Select ..., Sum(Case When account_subscriptiongroup.active Then 1 else 0 End) Over (Group By account_user.id) as total count
This just counts the records within the date range and having the desired actions.

How do i sum two query with each count and criteria in it

I have this two query sql and i'm trying to do a sum of both 2 counts in the query together but when i try to do the UNION ALL but it kept prompt me to enter parameter for CountOfTools_Number2. All i wan is the sum of the two count and return me a value.
SELECT Count(Test.Tool_Number) AS CountOfTool_Number1
FROM Test INNER JOIN Test_Tool ON Test.Tool_Number = Test_Tool.Current_Tool
GROUP BY Test_Tool.Current_Test
HAVING (((Test_Tool.Current_Test) Like "*E1*"));
SELECT Count(Test.Tool_Number) AS CountOfTool_Number2
FROM Test_Tool, Test INNER JOIN Previous_Tool ON Test.Tool_Number = Previous_Tool.Previous_Tool
GROUP BY Test_Tool.Current_Test
HAVING (((Test_Tool.Current_Test) Like "*E1*"));
Presuming your two example queries work, this should do the trick:
select
sum(CountOfTool_Number1) as CountOfTool
from (
SELECT Count(Test.Tool_Number) AS CountOfTool_Number1
FROM Test INNER JOIN Test_Tool ON Test.Tool_Number = Test_Tool.Current_Tool
GROUP BY Test_Tool.Current_Test
HAVING (((Test_Tool.Current_Test) Like "*E1*"))
union all
SELECT Count(Test.Tool_Number) AS CountOfTool_Number2
FROM Test_Tool, Test INNER JOIN Previous_Tool ON Test.Tool_Number = Previous_Tool.Previous_Tool
GROUP BY Test_Tool.Current_Test
HAVING (((Test_Tool.Current_Test) Like "*E1*"))
) as q;

How to create SQL view with Count()

This is my query:
select
Sales.SaleID,
Sales.StartSaleDate,
Sales.EndSaleDate,
Sales.SalePercent,
COUNT(LessonID) as TotalLesson,
Sales.Status,
Sales.ExpiredStatus,
Sales.SalePrice,
Sales.IsSpecial
FROM
Sales
LEFT JOIN
SaleLessons ON SaleLessons.SaleID = Sales.SaleID
GROUP BY
Sales.Status, Sales.IsSpecial, Sales.StartSaleDate, Sales.EndSaleDate,
Sales.SalePercent, Sales.SaleID, Sales.ExpiredStatus, Sales.SalePrice
ORDER BY
Sales.StartSaleDate DESC
create view ViewSchema.ViewName
as
select Sales.SaleID,
Sales.StartSaleDate,
Sales.EndSaleDate,
Sales.SalePercent,
COUNT(LessonID) as TotalLesson,
Sales.Status,
Sales.ExpiredStatus,
Sales.SalePrice,
Sales.IsSpecial
from Sales
LEFT JOIN SaleLessons
ON SaleLessons.SaleID = Sales.SaleID
group by Sales.Status,
Sales.IsSpecial,
Sales.StartSaleDate,
Sales.EndSaleDate,
Sales.SalePercent,
Sales.SaleID,
Sales.ExpiredStatus,
Sales.SalePrice
You really don't need the ORDER BY clause, you can use it later when extracting data from the view.
Also, here is a very informative answer on this subject - https://stackoverflow.com/a/15188437/7119478

sql query with group by and count

I have this ms access query:
SELECT weber, t1.artnr, t1.varnr, t1.lfdnr_kal, fert.invnr, fert.min, fert.[lst/h] FROM (
SELECT stammdat.weber, lackzahlen.artnr, lackzahlen.varnr, first(stammdat.[lfdnr-kal]) AS lfdnr_kal
FROM lackzahlen LEFT JOIN stammdat ON (lackzahlen.artnr=cstr(IIf(stammdat.artnr Is Null,'',cstr(stammdat.artnr)))) AND (lackzahlen.varnr=cstr(IIf(stammdat.varnr Is Null,'',cstr(stammdat.varnr))))
GROUP BY lackzahlen.artnr, lackzahlen.varnr, io_stkzahl, weber) AS t1
LEFT JOIN fert ON (t1.lfdnr_kal=fert.[lfdnr-kal]) AND (t1.artnr=cstr(iif(fert.artnr Is Null,'',cstr(fert.artnr)))) WHERE fert.invnr IN ('338902', 'R20000')
Now, I would like to filter the records on the image:
As you see, I would like to have the records, where there is pro weber, artnr, varnr, lfdnr_kal and invnr more than one row with the same min and lst/h value.
I guess, I should use cound (maybe having count) and group by. But how?
In the example, I haven't marked all the rows.
Add group by and having to get the duplicate rows
GROUP BY weber, t1.artnr, t1.varnr, t1.lfdnr_kal, fert.invnr, fert.min, fert.[lst/h]
having count(*) >1
Try below SQL : As you didnt mention sum or AVG values i guess distinct records will solve your problem.
select weber, a.artnr,a.varnr, a.lfdnr_kal, a.invnr, a.min, a.lst_h
(
SELECT weber, t1.artnr, t1.varnr, t1.lfdnr_kal, fert.invnr, fert.min, fert.[lst/h] as lst_h FROM (
SELECT stammdat.weber, lackzahlen.artnr, lackzahlen.varnr, first(stammdat.[lfdnr-kal]) AS lfdnr_kal
FROM lackzahlen LEFT JOIN stammdat ON (lackzahlen.artnr=cstr(IIf(stammdat.artnr Is Null,'',cstr(stammdat.artnr)))) AND (lackzahlen.varnr=cstr(IIf(stammdat.varnr Is Null,'',cstr(stammdat.varnr))))
GROUP BY lackzahlen.artnr, lackzahlen.varnr, io_stkzahl, weber) AS t1
LEFT JOIN fert ON (t1.lfdnr_kal=fert.[lfdnr-kal]) AND (t1.artnr=cstr(iif(fert.artnr Is Null,'',cstr(fert.artnr)))) WHERE fert.invnr IN ('338902', 'R20000')
) a group by weber, a.artnr,a.varnr, a.lfdnr_kal, a.invnr, a.min, a.lst_h
Having count(*) > 1
Hope this helps :)

Column is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause

Ok here's my View (vw_LiftEquip)
SELECT dbo.tbl_equip_swl_unit.unit_id,
dbo.tbl_equip_swl_unit.unit_name,
dbo.tbl_equip_swl_unit.archived,
dbo.tbl_categories.category_id,
dbo.tbl_categories.categoryName,
dbo.tbl_categories.parentCategory,
dbo.tbl_categories.sub_category,
dbo.tbl_categories.desc_category,
dbo.tbl_categories.description,
dbo.tbl_categories.miscellaneous,
dbo.tbl_categories.category_archived,
dbo.tbl_equip_swl_unit.unit_name AS Expr1,
dbo.tbl_categories.categoryName AS Expr2,
dbo.tbl_categories.description AS Expr3,
dbo.tbl_equip_depts.dept_name,
dbo.tbl_equip_man.man_name,
dbo.tbl_Lifting_Gear.e_defects AS Expr7,
dbo.tbl_Lifting_Gear.e_defects_desc AS Expr8,
dbo.tbl_Lifting_Gear.e_defects_date AS Expr9,
dbo.tbl_equipment.equipment_id,
dbo.tbl_equipment.e_contract_no,
dbo.tbl_equipment.slID,
dbo.tbl_equipment.e_entered_by,
dbo.tbl_equipment.e_serial,
dbo.tbl_equipment.e_model,
dbo.tbl_equipment.e_description,
dbo.tbl_equipment.e_location_id,
dbo.tbl_equipment.e_owner_id,
dbo.tbl_equipment.e_department_id,
dbo.tbl_equipment.e_manafacture_id,
dbo.tbl_equipment.e_manDate1,
dbo.tbl_equipment.e_manDate2,
dbo.tbl_equipment.e_manDate3,
dbo.tbl_equipment.e_dimensions,
dbo.tbl_equipment.e_test_no,
dbo.tbl_equipment.e_firstDate1,
dbo.tbl_equipment.e_firstDate2,
dbo.tbl_equipment.e_firstDate3,
dbo.tbl_equipment.e_prevDate1,
dbo.tbl_equipment.e_prevDate2,
dbo.tbl_equipment.e_prevDate3,
dbo.tbl_equipment.e_insp_frequency,
dbo.tbl_equipment.e_swl,
dbo.tbl_equipment.e_swl_unit_id,
dbo.tbl_equipment.e_swl_notes,
dbo.tbl_equipment.e_cat_id,
dbo.tbl_equipment.e_sub_id,
dbo.tbl_equipment.e_parent_id,
dbo.tbl_equipment.e_last_inspector,
dbo.tbl_equipment.e_last_company,
dbo.tbl_equipment.e_deleted AS Expr11,
dbo.tbl_equipment.e_deleted_desc AS Expr12,
dbo.tbl_equipment.e_deleted_date AS Expr13,
dbo.tbl_equipment.e_deleted_insp AS Expr14,
dbo.tbl_Lifting_Gear.e_defects_action AS Expr15,
dbo.tbl_equipment.e_rig_location,
dbo.tbl_Lifting_Gear.e_add_type AS Expr17,
dbo.tbl_Lifting_Gear.con_id,
dbo.tbl_Lifting_Gear.lifting_date,
dbo.tbl_Lifting_Gear.lifting_ref_no,
dbo.tbl_Lifting_Gear.e_id,
dbo.tbl_Lifting_Gear.inspector_id,
dbo.tbl_Lifting_Gear.lift_testCert,
dbo.tbl_Lifting_Gear.lift_rig_location,
dbo.tbl_Lifting_Gear.inspected,
dbo.tbl_Lifting_Gear.lifting_through,
dbo.tbl_Lifting_Gear.liftingNDT,
dbo.tbl_Lifting_Gear.liftingTest,
dbo.tbl_Lifting_Gear.e_defects,
dbo.tbl_Lifting_Gear.e_defects_desc,
dbo.tbl_Lifting_Gear.e_defects_date,
dbo.tbl_Lifting_Gear.e_defects_action,
dbo.tbl_Lifting_Gear.lift_department_id,
dbo.tbl_Lifting_Gear.lifting_loc
FROM dbo.tbl_equipment
INNER JOIN dbo.tbl_equip_swl_unit
ON dbo.tbl_equipment.e_swl_unit_id = dbo.tbl_equip_swl_unit.unit_id
INNER JOIN dbo.tbl_categories
ON dbo.tbl_equipment.e_cat_id = dbo.tbl_categories.category_id
INNER JOIN dbo.tbl_equip_depts
ON dbo.tbl_equipment.e_department_id = dbo.tbl_equip_depts.dept_id
INNER JOIN dbo.tbl_equip_man
ON dbo.tbl_equipment.e_manafacture_id = dbo.tbl_equip_man.man_id
INNER JOIN dbo.vwSubCategory
ON dbo.tbl_equipment.e_sub_id = dbo.vwSubCategory.category_id
INNER JOIN dbo.vwDescCategory
ON dbo.tbl_equipment.e_cat_id = dbo.vwDescCategory.category_id
INNER JOIN dbo.tbl_Lifting_Gear
ON dbo.tbl_equipment.equipment_id = dbo.tbl_Lifting_Gear.e_id
And here's the select statement with subquery that I am using:
SELECT *
FROM vw_LiftEquip
WHERE lifting_loc = ? AND
con_id = ? AND
EXPR11 =
'N'(
SELECT MAX(lifting_date) AS maxLift
FROM vw_LiftEquip
WHERE e_id = equipment_id
)
ORDER BY lifting_ref_no,
category_id,
e_swl,
e_serial
I get the error :
Column "vw_LiftEquip.category_id" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
Can't see why its returning that error, this is admittedly the first time I've ran a subquery on such a complex view, and I am a bit lost, thanks in advance for any help. I have looked through the similar posts and can find no answers to this one, sorry if I am just being dumb.
You are missing AND between EXPR11 = 'N' and (SELECT MAX(...
Otherwise, it looks OK. MAX without GROUP BY is allowed if you have no other columns in the SELECT
Update: #hvd also noted that you have nothing to compare to MAX(lifting_date). See comment
Update 2,
SELECT *
FROM vw_LiftEquip v1
CROSS JOIN
(
SELECT MAX(lifting_date) AS maxLift
FROM vw_LiftEquip
WHERE e_id = equipment_id
) v2
WHERE v1.lifting_loc = ? AND
v1.con_id = ? AND
v1.EXPR11 = 'N'
ORDER BY v1.lifting_ref_no,
v1.category_id,
v1.e_swl,
v1.e_serial