counting methodolegy in SQL Server query - sql-server-2008

Good day everyone…
I have a database that has the following:
Division table that linked to Employee table.
Group table, i.e. courses categories, that linked to Courses table.
and these table linked together thru Curses_Employee table .
so far I managed to come up with a query that give me the number of users who toke certain course in each group/category like the following output table:
groupName | DivisionName| courseName|Total Number of Participants
and here is my query for the above scheme:
SELECT dbo.groups.GroupName, dbo.Divisions.DivisionName, dbo.courses.CourseName, COUNT(dbo.employee_courses.courseId) AS [Total Number of Participants]
FROM dbo.employee AS employee_1 INNER JOIN
dbo.Divisions ON employee_1.DivisionCode = dbo.Divisions.SapCode INNER JOIN
dbo.employee_courses ON employee_1.Username = dbo.employee_courses.employeeId INNER JOIN
dbo.courses ON dbo.employee_courses.courseId = dbo.courses.CourseID INNER JOIN
dbo.groups ON dbo.courses.GroupID = dbo.groups.ID
WHERE (dbo.courses.GroupID = 2)
GROUP BY dbo.courses.CourseID, dbo.courses.CourseName, dbo.Divisions.DivisionName, dbo.groups.GroupName
now I want to add two columns the total number of employee in each division as well as the % like the following table:
groupName | DivisionName| courseName|Total Number of Participants |Total Number of Employee |%
I tried this query but it give me an error:
SELECT dbo.groups.GroupName, dbo.Divisions.DivisionName, dbo.courses.CourseName, COUNT(dbo.employee_courses.courseId) AS [Total Number of Participants],
(SELECT COUNT(Name) AS Expr1
FROM dbo.employee
WHERE (DivisionCode = employee_1.DivisionCode)
GROUP BY DivisionCode) AS [Total Number of Employee]
FROM dbo.employee AS employee_1 INNER JOIN
dbo.Divisions ON employee_1.DivisionCode = dbo.Divisions.SapCode INNER JOIN
dbo.employee_courses ON employee_1.Username = dbo.employee_courses.employeeId INNER JOIN
dbo.courses ON dbo.employee_courses.courseId = dbo.courses.CourseID INNER JOIN
dbo.groups ON dbo.courses.GroupID = dbo.groups.ID
WHERE (dbo.courses.GroupID = 2)
GROUP BY dbo.courses.CourseID, dbo.courses.CourseName, dbo.Divisions.DivisionName, dbo.groups.GroupName
the error message:
column 'dbo.employee.DivisionCode' is invalid in the select list
because it is not contained in either as aggregate function or the
GROUP BY clause.

Related

Need count of transactional table based on other tables including zeros where there are no matches

I have four tables, three of which are pretty static: haul_types, dumpster_type_team (the dumpster_type_team has the many-to-many relationship between dumpster_types and teams), and users. The fourth table, hauls, has transactional data.
haul_types:
id
name
dumpster_type_team:
id
dumpster_type_id
team_id
users:
id
first_name
last_name
is_driver
team_id
hauls:
haul_type_id
haul_status_id
set_dumpster_type_id
completed_driver_id
team_id
I would like a query that has a combination of dumpster_types, haul_types, and drivers (users) and a count of the hauls they were involved in. In some cases, there should be a count of zero because some drivers haven't completed hauls for every haul_type / dumpster type combination.
Here's the query I have so far that seems to be behaving as if it is an inner join because the records are getting filtered to only show where there are matches:
SELECT
c.haul_type_id,
c.dumpster_type_id,
c.driver_id,
count(h.id) AS haul_count
FROM
hauls h
RIGHT JOIN ( SELECT DISTINCT
ht.id AS haul_type_id,
dtt.dumpster_type_id AS dumpster_type_id,
dtt.team_id AS team_id,
u.id AS driver_id
FROM
haul_types ht
CROSS JOIN dumpster_type_team dtt
CROSS JOIN users u
WHERE
u.team_id = dtt.team_id
AND u.is_driver = TRUE) c ON c.haul_type_id = h.haul_type_id
AND c.dumpster_type_id = h.set_dumpster_type_id
AND c.driver_id = h.completed_driver_id
AND c.team_id = h.team_id
WHERE
h.team_id = 9
AND h.haul_status_id = 3
AND h.completed_driver_id IS NOT NULL
GROUP BY
c.haul_type_id, c.dumpster_type_id, c.driver_id
When I run the subquery in isolation:
SELECT DISTINCT
ht.id AS haul_type_id,
dtt.dumpster_type_id AS dumpster_type_id,
dtt.team_id AS team_id,
u.id AS driver_id
FROM
haul_types ht
CROSS JOIN dumpster_type_team dtt
CROSS JOIN users u
WHERE
u.team_id = dtt.team_id
AND u.is_driver = TRUE
I get the results I want: a row for each permutation of haul_type, dumpster_type, driver_id, and team_id. However, when I run the entire query, I get filtered results despite the right join.
What I would like to have is the following:
If I have 4 haul_types: delivery, swap, live, pickup
and 2 dumpster_types: 10YD, 15YD
and 2 drivers: 1, 2
I would like a haul count for the combination of haul_type, dumpster_type, and driver. If there are no hauls matching the row, show 0:
Any help is appreciated. Thank you
The description of the question and the query seem to have little to do with each other. I don't know what a "pivot table" is supposed to be.
I would like a query that has a combination of dumpster_types, haul_types, and drivers (users) and a count of the hauls they were involved in.
This sounds like a cross join to generate the rows and then a left join/group by to calculate the results:
select d.dumpster_id, ht.haul_type_id, d.driver_id, count(h.driver_id)
from dumpster_types d cross join
haul_types ht cross join
drivers d left join
hauls h
on h.dumpster_id = d.dumpster_id and
h.haul_type_id = ht.haul_type_id and
h.driver_id = d.driver_id
group by d.dumpster_id, ht.haul_type_id, d.driver_id;
Running the query #GordonLinoff provided, exposed the issue I was facing - when applying a where clause on the top level query, the results were getting filtered to only matches. I moved the where clause to individual subqueries and now I am getting all expected results.
Not sure if this is the most efficient way to write it but it yields the correct results:
SELECT
d.dumpster_type_id,
ht.id AS haul_type_id,
u.id AS driver_id,
count(h.id) AS haul_count
FROM (
SELECT
dumpster_type_id,
team_id
FROM
dumpster_type_team
WHERE
team_id = 9) d
CROSS JOIN haul_types ht
CROSS JOIN (
SELECT
users.id
FROM
users
WHERE
users.is_driver = TRUE
AND users.team_id = 9) u
LEFT JOIN (
SELECT
id, set_dumpster_type_id, haul_type_id, completed_driver_id, team_id
FROM
hauls
WHERE
haul_status_id = 3
AND team_id = 9) h ON h.set_dumpster_type_id = d.dumpster_type_id
AND h.haul_type_id = ht.id
AND h.completed_driver_id = u.id
AND h.team_id = d.team_id
GROUP BY
d.dumpster_type_id,
ht.id,
u.id

Get several data from SQL query based on different conditions

I have the following code:
SELECT DISTINCT m.solde_total_client
,c.client_nom
,co.contenant_nom
FROM `mouvement` m, `client` c, `contenant` co
WHERE c.client_id = m.client_id
AND co.contenant_id = m.contenant_id
ORDER BY m.movement_date DESC
LIMIT 1;
And I get as a result one total sold of one client. But I want to get one for each contenant for each client. (But it still need to be the last one by date)
I'm getting as a result:
And I want to get several result like that such as:
Leclerc | Geobox | 50
SuperU | Box | 40
...
sold_total_client is what the client as after a shipment, there is several shipment and the sold is updated at every move, so the last one by date is the actual sold. So I have to get the last move of every contenant of every client.
You could try using a subquery for max_date group by client_id, contenant_id
SELECT
m.solde_total_client,
m.`mouvement_date`,
c.client_nom,
co.contenant_nom
FROM
`mouvement` m
INNER JOIN
(SELECT
MAX(mouvement_date) max_date, client_id, contenant_id
FROM
`mouvement`
GROUP BY
client_id, contenant_id) t ON t.client_id = m.client_id
AND m.contenant_id = t.contenant_id
AND t.max_date = m.`mouvement_date`
INNER JOIN
`client` c ON c.client_id = m.client_id
INNER JOIN
`contenant` co ON co.contenant_id = m.contenant_id
ORDER BY
m.`mouvement_date`

Retrieve all the values that are in the the row with the max value

I have a table that looks like this:
For each COMPANY there are multiple NATURAL_PERSON_ID, every NATURAL_PERSON have a date in which an audit was performed FECHA_DE_REPORTE and as a company there is a date in which the first loan was give to that company.
What I want is to select for each NATURAL_PERSON all the FOLIO_CONSULTA whose FECHA_DE_REPORTE is less or equal to FIRST_LOAN (the date in which the first loan was given for that company) Then I need to find the MAX date among each group and keep al the information (the whole row) for the value that fulfills all these conditions, and all this for each NATURAL_PERSON
So for this example the result I expected is all the information of the second row since this is the MAX() of FECHA_DE_REPORTE by COMPANY AND NATURAL_PERSON.
I have tried:
SELECT NPC.COMPANY_ID
,NPC.NATURAL_PERSON_ID
,NPS.DIGITAL_SIGNATURE_ID
,CDC.FOLIO_CONSULTA
,CDC.FECHA_DE_REPORTE
,FIRST_LOAN.FIRST_LOAN
,MAX(CDC.FECHA_DE_REPORTE) MAX_FOLIO_CONSUTA
FROM KONFIO.NATURAL_PERSON_COMPANY NPC
LEFT JOIN KONFIO.NATURAL_PERSON_SIGNATURE NPS ON NPS.NATURAL_PERSON_ID = NPC.NATURAL_PERSON_ID
JOIN KONFIO.CDC_RESPONSE CDC ON CDC.DIGITAL_SIGNATURE_ID= NPS.DIGITAL_SIGNATURE_ID
JOIN
(
SELECT CAPP.COMPANY_ID
,MIN(LOAN.DOCUMENTATION_DATE) FIRST_LOAN
FROM KONFIO.COMPANY_APPLICATION CAPP
JOIN KONFIO.LOAN ON LOAN.APPLICATION_ID = CAPP.APPLICATION_ID
GROUP BY CAPP.COMPANY_ID) FIRST_LOAN ON FIRST_LOAN.COMPANY_ID = NPC.COMPANY_ID
WHERE CDC.FECHA_DE_REPORTE <= FIRST_LOAN.FIRST_LOAN
AND NPC.COMPANY_ID IN (1033)
GROUP BY NPC.COMPANY_ID, NPC.NATURAL_PERSON_ID
but it retrieves the first value that finds so the FOLIO_CONSULTA does not correspond to the FOLIO_CONSULTA of the MAX() FECHA_DE_REPORTE
Any help would be appreciated
You should join the subquery for MAX(FECHA_DE_REPORTE) on table CDC_RESPONSE
SELECT NPC.COMPANY_ID
,NPC.NATURAL_PERSON_ID
,NPS.DIGITAL_SIGNATURE_ID
,CDC.FOLIO_CONSULTA
,CDC.FECHA_DE_REPORTE
,FIRST_LOAN.FIRST_LOAN
,T.MAX_FOLIO_CONSUTA
FROM KONFIO.NATURAL_PERSON_COMPANY NPC
INNER JOIN (
SELECT DIGITAL_SIGNATURE_ID
, MAX(FECHA_DE_REPORTE) MAX_FOLIO_CONSUTA
FROM KONFIO.CDC_RESPONSE
GROUP BY DIGITAL_SIGNATURE_ID
) T ON T.DIGITAL_SIGNATURE_ID = NPS.DIGITAL_SIGNATURE_ID
AND T.MAX_FOLIO_CONSUTA = CDC.FECHA_DE_REPORTE
LEFT JOIN KONFIO.NATURAL_PERSON_SIGNATURE NPS ON NPS.NATURAL_PERSON_ID = NPC.NATURAL_PERSON_ID
JOIN KONFIO.CDC_RESPONSE CDC ON CDC.DIGITAL_SIGNATURE_ID= NPS.DIGITAL_SIGNATURE_ID
JOIN
(
SELECT CAPP.COMPANY_ID
,MIN(LOAN.DOCUMENTATION_DATE) FIRST_LOAN
FROM KONFIO.COMPANY_APPLICATION CAPP
JOIN KONFIO.LOAN ON LOAN.APPLICATION_ID = CAPP.APPLICATION_ID
GROUP BY CAPP.COMPANY_ID) FIRST_LOAN ON FIRST_LOAN.COMPANY_ID = NPC.COMPANY_ID
WHERE CDC.FECHA_DE_REPORTE <= FIRST_LOAN.FIRST_LOAN
AND NPC.COMPANY_ID IN (1033)
GROUP BY NPC.COMPANY_ID, NPC.NATURAL_PERSON_ID
...... missing part

mysql several count and join returns strange value

I'm trying to make a count within several table with JOIN, but when I made several JOINs the COUNTs got wrongly counted.
Basically I've got 4 tables, named:
predective_search
predective_to_product
predective_to_category
predective_to_manufacturer
I want to count the total number of products, categories and manufacturer which has same id in table predective_search.
Here's my code:
SELECT * ,
COUNT(pp.predictive_id) AS total_products,
COUNT(pc.predictive_id) AS total_categories,
COUNT(pm.predictive_id) AS total_manufacturers
FROM predictive_search ps
LEFT JOIN predictive_to_product pp ON (ps.predictive_id = pp.predictive_id)
LEFT JOIN predictive_to_category pu ON (ps.predictive_id = pc.predictive_id)
LEFT JOIN oc_predictive_to_manufacturer pm ON (ps.predictive_id = pm.predictive_id)
GROUP BY ps.predictive_id
Also the GROUP BY is needed I think. I'm stuck at this as I'm not getting any way to do this
SELECT
ps.*,
agg_pp.total_products,
agg_pc.total_categories,
agg_pm.total_manufacturers
FROM predictive_search ps
LEFT JOIN (
SELECT pp.predictive_id, COUNT(*) AS total_products
FROM predictive_to_product pp
GROUP BY pp.predictive_id
) agg_pp ON ps.predictive_id = agg_pp.predictive_id
LEFT JOIN (
SELECT pc.predictive_id, COUNT(*) AS total_categories
FROM predictive_to_category pc
GROUP BY pc.predictive_id
) agg_pc ON ps.predictive_id = agg_pc.predictive_id
LEFT JOIN (
SELECT pm.predictive_id, COUNT(*) AS total_manufacturers
FROM predictive_to_category pm
GROUP BY pm.predictive_id
) agg_pm ON ps.predictive_id = agg_pm.predictive_id

avg in query - mysql

I have this query
SELECT salary
FROM worker W
JOIN single_user U ON u.users_id_user = W.single_user_users_id_user
JOIN university_has_single_user US ON US.single_user_users_id_user = U.users_id_user
JOIN course C ON C.id_course = US.course_id_course
JOIN formation_area FA ON FA.id_formation_area = C.formation_area_id_formation_area
WHERE FA.area = "Multimédia"
GROUP BY users_id_user
...that gave this output:
salary
--------
1400.00
800.00
How can I calculate the avg of this output? If I add:
SELECT round(avg (salary), 0)
...the output is again 1400.00 and 800.00, not the avg (because the group by).
Use:
SELECT AVG(DISTINCT salary)
FROM worker W
JOIN single_user U ON u.users_id_user = W.single_user_users_id_user
JOIN university_has_single_user US ON US.single_user_users_id_user = U.users_id_user
JOIN course C ON C.id_course = US.course_id_course
JOIN formation_area FA ON FA.id_formation_area = C.formation_area_id_formation_area
WHERE FA.area = "Multimédia"
Because the salary column is not wrapped in an aggregate, per the documentation, the values you see are arbitrary (can't be guaranteed 100% of the time).
Usually, you'd need a derived table to get the average of the distinct values but MySQL's AVG supports using DISTINCT within it.