I'm having trouble creating a query that will report on training completions by users that are grouped by district within a region. For one training course the report needs to show for each district
Number of users assigned course
Number of users completed course
Percentage of users completed course
The output report should look like this (without the periods).:
District.........Assigned.......Completed....%
Arkansas..........20..............15...............75%
Illinois...............80..............80...............100%
Iowa.................10...............8.................80%
Michigan..........30..............20................66%
Here's the SQL query I have tried using
Select mytable.district as District,
(Select Count(Distinct mytable.user_id)
From mytable
Where mytable.district = District AND
mytable.training_title = 'My Course') As 'Assigned',
(Select Count(Distinct mytable.user_id)
From mytable
Where mytable.training_status = "Completed" AND
mytable.district = District AND
mytable.training_title = 'My Course') as 'Completed',
Concat(Round(100 * (Select Count(Distinct mytable.user_id)
From mytable
Where mytable.training_status = "Completed" AND
mytable.district = District AND
mytable.training_title = 'My Course') / (Select Count(Distinct mytable.user_id)
From mytable
Where
mytable.district = District AND
mytable.training_title = 'My Course'),0 ),"%") as '%'
From mytable
Where mytable.region = 'Midwest'
Group by District
It doesn't work at all like this. However if I substitute one of the district values (such as Arkansas) in for 'District' in the WHERE clause I can get the correct values for that district. However i need to find all of the districts for each region and calculate the values for district. This is only one of the regions I need to create the query for.
Two key issues:
All of the data exists in one table in my database. I have consolidated and imported it from another database.
The data contains duplicates Therefore I must use Distinct to eliminate the duplicates from the results.
Suggestions? Thanks in advance for your assistance!!!
As far as I can see, you could just sum things up as you want them and GROUP BY district. The subquery will take care of the duplicate rows.
SELECT
district,
COUNT(*) Assigned,
COUNT(CASE WHEN training_status='Completed' THEN 1 END) Completed,
CONCAT(COUNT(CASE WHEN training_status='Completed' THEN 1 END) /
COUNT(*) * 100, '%') `%`
FROM (
SELECT DISTINCT * FROM mytable
WHERE mytable.region = 'Midwest'
AND mytable.training_title = 'My Course') z
GROUP BY district;
An SQLfiddle to test with.
Related
I have a problem selecting the data from a table. I'm sure the answer is staring me in the face, but my brain is mush. We're trying to find out which customers have bought based on only email blasts and nothing else. I can easily select any row where salesPrompt = 'email' but that might still include folks that also bought due to salesPrompt = 'postcard' or some other method. How do I select only customers that bought due the email blast? I've tried:
SELECT * FROM `customer_sales` WHERE `salesPrompt` = 'email' GROUP BY `accountID`
But that still brought up customers that had salesPrompt equaling other values.
you should check for count distint salePrompt using having and join the result
select s.*
FROM `customer_sales`
inner join (
SELECT accountID
FROM `customer_sales`
GROUP BY `accountID`
having count(distinct salesPrompt) = 1
) t on t.accountID = s.accountID
where `salesPrompt` = 'email'
Another possibility is to select all entries having the desired salesPrompt and then exclude (using EXISTS) all entries that also have further salesPrompts and the same accountid. Assuming, you want to name the main selection "target", this looks like this:
SELECT salesprompt, accountid
FROM customer_sales AS target WHERE salesprompt = 'email'
AND NOT EXISTS (SELECT 1 FROM customer_sales WHERE salesprompt != 'email'
AND accountid = target.accountid);
here is my current query and it access four tables. Everything else displays the correct data except for this part:
IF(tbl_shift.commission IS NULL,'0.00', (tbl_shift.commission*tbl_payment.subtotal)) AS comm,
this doesn't seem to access the data from the table.
Here is the full query:
SELECT tbl_payment.dateTime AS purchasedate, tbl_payment.invoiceNo AS invoice,
tbl_payment.subtotal AS total, tbl_payment.staffid AS employee,
tbl_users.fname AS firstname, tbl_users.lname AS lastname,
IF(tbl_shift.commission IS NULL,'0.00', (tbl_shift.commission*tbl_payment.subtotal)) AS comm,
(SELECT COUNT(1) AS qty FROM tbl_purchases
WHERE tbl_payment.invoiceNo=tbl_purchases.invoiceNo) AS qty
FROM `tbl_payment`
LEFT JOIN tbl_shift ON tbl_payment.staffid = tbl_shift.employeeId
AND tbl_payment.dateTime BETWEEN tbl_shift.startShift
AND tbl_shift.endShift
INNER JOIN tbl_users ON tbl_payment.staffid = tbl_users.id
WHERE tbl_payment.staffid = ".$staff."
AND dateTime BETWEEN '".$from."' AND '".$to."'
ORDER BY tbl_payment.dateTime DESC
if this succeeds
IF(tbl_shift.commission IS NULL,'0.00', (tbl_shift.commission*tbl_payment.subtotal)) AS comm,
Wouldn't it mean that you would have both string values and numbers in the same column if both are true for any rows?
Perhaps try this and see what happens:
IF(ISNULL(tbl_shift.commission)=1,0,(tbl_shift.commission*tbl_payment.subtotal)) AS comm,
I used for a while Stack, you help me a lot ... this is my first question, I hope to be able to expose correctly.
I need to retrieve all value from a table and add one column with sum value from another table.
This what I mean:
q1=>
SELECT * FROM users WHERE role >30 AND role <50 AND available = 1 AND active = 1
to q1 add a new column from q2=>
SELECT SUM(budget) AS totalBudget FROM projects_assignments
Relation between tables are idUser
more over in projects_assignments I have some users of users' table and some user is in projects_assignments only one time.
example:
table1 = idUser, some values
table2 = idUser, budget, other es: values (1,10000,40),(1,5000,30),(2,5000,30)
My expected result is:
idUser,table1column1,table1column2,totalBudget
1,x,y,15000(10k+5k)
2,x,x,5000
3,x,y,0
...
n,x,y,0
Thanks a lot,
Matteo
select table1.column1,
table1.column2,
table1.column3,
sum(table2.budget) as totalBudget
from table1
inner join table2
on table1.idUser = table2.idUser
where...
group by table1.idUser
Assume a database with schema
TRUCK (license-plate, maker, model, year, mileage, max-load)
DRIVER (driver-id, name, age, address, license)
TRIP (license-plate, driver-id, date, origin, destination, miles, cargo, cost)
Write a SQL statement to list the names and driver-id of drivers who have taken trips to New York more times than they have taken trips to Washington.
I'm trying to express with something like
SELECT
name, driver-id
FROM
DRIVER, TRIP,
(SELECT name, driver-id
FROM DRIVER, TRIP
WHERE TRIP.driver-id = DRIVER.driver-id AND destination = “Washington”
GROUP BY name, driver-id) as TEMP
WHERE
TRIP.driver-id = DRIVER.driver-id
AND destination = “New York”
AND DRIVER.driver-id = TEMP.driver-id
GROUP BY
name, driver-id
HAVING
COUNT(*) > TEMP.COUNT(*);
Is this correct? Thanks!
I think you only need to aggregate by driver here and then assert that the count of trips to New York exceeds the count of trips to Washington:
SELECT
d.name,
d.driverid
FROM DRIVER d
INNER JOIN TRIP t
ON d.driverid = t.driverid
GROUP BY
d.name,
d.driverid
HAVING
SUM(t.destination = 'New York') >
SUM(t.destination = 'Washington');
This approach just makes a single pass over the joined tables using conditional aggregation for the two counts. I would not normally use your approach, because of the large subquery in the select clause.
use aggregation sum() and case keyword
select * from (
SELECT d.name, d.driver-id
, sum(case when destination = 'Washington' then 1 else 0 end) as washington
, sum(case when destination = 'New York' then 1 else 0 end) as newyork
FROM DRIVER d
INNER JOIN TRIP t ON t.driver-id = d.driver-id
GROUP BY d.name, d.driver-id) t1
where t1.newyork > t1.washington
I have to list the difference between the number of tickets sold at the different
stations of one line between time1 and time2. I have three table: time1, time 2 and place.
create table fares_jan18 (
station varchar(100),
ff int
);
create table fares_feb1 (
station varchar(100),
ff int
);
create table stations (
name varchar(100),
line varchar(50)
);
I'm using this query:
SELECT
fares_jan18.station AS name,
SUM(fares_feb1.ff - fares_jan18.ff) AS diff_feb1_jan18
FROM
fares_jan18
JOIN fares_feb1 ON fares_jan18.station = fares_feb1.station
JOIN stations ON fares_jan18.station = stations.name
WHERE
stations.line ="Broadway"
GROUP BY
name
ORDER BY
name;
it does give me the correct table, but when ever there is more that one record, I get the duplicate the sum of the difference. For instance the result for a station with two values should be 33254, and it' giving me 66508. I have removed the group by from my query, it seems that I have for records instead of two.
I've read all I could on StackOverflow but I can't get my head around what I'm doing wrong? Thanks!!
Here is an image of my table:
You're creating a cartesian product of all the rows with the same stations in the two fares tables, and then summing the differences from each pair. You need to calculate the totals in each table separately in subqueries, and then subtract them.
SELECT s.name, feb1.total - jan18.total AS diff_feb1_jan18
FROM stations AS s
JOIN (SELECT station, SUM(ff) AS total
FROM fares_feb1
GROUP BY station) AS feb1
ON feb1.station = s.station
JOIN (SELECT station, SUM(ff) AS total
FROM fares_jan18
GROUP BY station) AS jan18
ON jan18.station = s.station
WHERE s.line = "Broadway"
ORDER BY s.name
You need to pre-aggregate each separately or you are getting a Cartesian result... Since the query is for a single Broadway, a single record will result in each station when working the join from each date data source
SELECT
justF18.name,
justFeb1.SumFF - justF18.SumFF as FF_Diff
from
( SELECT f18.station AS name,
SUM(f18.ff) AS Sumff
FROM
fares_jan18 f18
JOIN stations s ON f18.station = s.name
AND s.line = "Broadway"
group by
f18.station ) justF18
JOIN
( SELECT feb1.station AS name,
SUM(feb1.ff) AS Sumff
FROM
fares_feb1 feb1
JOIN stations s ON feb1.station = s.name
AND s.line = "Broadway"
group by
feb1.station ) justFeb1
ON justF18.name = justFeb1.name
order by
JustFeb18.name