Access sql statement with multiple sums and joins - ms-access

I am trying to get the sum of two different fields from different tables but no matter what i do one of the fields gets doubled. Below is my statement. Any help would be greatly appreciated it!
SELECT subq.[Opportunity ID],
sum(subq.[Buy Price]) as [Buy Price],
sum(subq.ProjectAmt) as [ProjectAmt]
FROM ( SELECT Distinct s.[Opportunity ID] as [Opportunity ID],
s.[Buy Price] as [Buy Price],
i.[ProjectAmt] as [ProjectAmt]
FROM SF_SKU_Data s
Inner join [ProjectInvoice] i on i.[Opportunity ID] = s.[Opportunity ID]
Group by s.[Opportunity ID], s.[Buy Price], i.[ProjectAmt]
) AS subq
GROUP BY subq.[Opportunity ID]

Related

Using Max Count after joining two tables in MySql

I am just a beginner in MySql and I am trying to display the worker ID, full name and the maximum number of assignments issued to a particular employee(worker). The two tables worker and assignment are related through Wrk_ID.
My code is not working.
SELECT w.Wrk_ID,
CONCAT_WS(" ", Wrk_FirstName, Wrk_Initial, Wrk_LastName) AS FullName,
COUNT(a.Wrk_ID) AS count
FROM worker w LEFT JOIN assignment a
ON w.Wrk_ID = a.Wrk_ID
GROUP BY w.Wrk_ID
HAVING count = ALL(SELECT MAX(a.Wrk_ID) FROM assignment GROUP BY Wrk_ID);
Really need assistance!...Thanks
Try this
SELECT distinct w.Wrk_ID,
CONCAT_WS(" ", Wrk_FirstName, Wrk_Initial, Wrk_LastName) AS FullName,
COUNT(a.Wrk_ID) AS count
FROM worker w LEFT JOIN assignment a
ON w.Wrk_ID = a.Wrk_ID
GROUP BY w.Wrk_ID
HAVING count >= ALL(SELECT count(Wrk_ID) FROM assignment GROUP BY Wrk_ID);
SQL Fiddle - http://sqlfiddle.com/#!9/b6e2b/10

Built in Functions and Grouping is not working in Microsoft Access

I am trying to select from three tables using inner join in Microsoft Access. in one of the fields, i also need to select how many records did it return.
SELECT Person.FirstName, Person.LastName, Person.Phone,
Person.Email,Person.Address, Room.RoomNo, Room.Type, Building.Name,
Floor.Name,count(*) as result
FROM (Floor INNER JOIN (Building INNER JOIN
Room ON Building.BuildingID = Room.BuildingID) ON Floor.FloorNo =
Room.FloorNo) INNER JOIN (Person INNER JOIN Patient ON Person.Username =
Patient.Username) ON Room.RoomNo = Patient.RoomNo
WHERE (((Person.FirstName) Like "*" & [Forms]![search]![firstnameKey] & "*")
AND ((Person.LastName) Like "*" & [Forms]![search]![lastnameKey] & "*")) AND
(patient.status = 1)
GROUP BY Patient.username ;
Any time you have an aggregate function you'll have to group by the fields not being calculated. Just from looking at your select statement you are returning multiple fields, i.e: Person.Firstname, Person.Lastname etc. I believe you will have to group by those non-aggregated fields.
Sample Code:
SELECT Person.FirstName, Person.LastName, Person.Phone, Person.Email, Person.Address, Count(*) as Result <br>
From Table1 join table 2 -- etc <br>
WHERE a = b -- etc <BR>
GROUP BY Person.FirstName, Person.LastName, Person.Phone, Person.Email, Person.Address

Getting SUM of two distinct procedure

I have two procedures that calculate two data. Now i would like to get the sum of those two output. Is it possible in sql?
ex:
Select bio.*,
SUM (cnt_report,cnt_report_2) as TOTAL --CAN I DO THIS?
cnt_report + cnt_report_2 as Total --This doesn't seem to work
from biographical bio
LEFT JOIN (
SELECT cr.id, COUNT (*) AS cnt_report
FROM report cr
GROUP BY cr.id
) cr11 ON bio.id = cr11.id
LEFT JOIN (
SELECT cr.id2,
COUNT (*) AS cnt_report_2
FROM report cr
GROUP BY cr.id2
) cr11 ON bio.id = cr11.id2
Your Sum function will work with a little tweak, but you will need to add a GROUP BY line at the end. Also, you seem to have named your two sub queries with the same alias. Try this:
Select bio.*,
SUM (cr11_1.cnt_report + cr11_2.cnt_report_2) as TOTAL
from biographical bio
LEFT JOIN (
SELECT cr.id, COUNT (*) AS cnt_report
FROM report cr
GROUP BY cr.id
) cr11_1 ON bio.id = cr11_1.id
LEFT JOIN (
SELECT cr.id2,
COUNT (*) AS cnt_report_2
FROM report cr
GROUP BY cr.id2
) cr11_2 ON bio.id = cr11_2.id2
GROUP BY bio.*
You can not do this:
sum(something, something_else)
but you can do this:
sum(something + something_else)
You can figure out how to implement that into your query. Remember that if you are selecting other fields along with an aggregate, you need a group by clause.

MS Access - Rank on TEXT fields

In MS Access 2000, I have a table named [Stack Trace] from which I should randomly pull 400 records with distinct of one of the text columns.
I looked at one of the examples in here and added an autonumber field to the table and wrote the query as below:
Assume that [Appraisal Name] is the distinct field needed and ID is the autonumbered primary key, what should be the query to find random 400 records with one of the text fields having distinct values?
First query without Distinct [Appraisal Name].
SELECT Top 400 *
FROM (SELECT *,
Rnd(ID) AS RandomValue
FROM [Street Data])
ORDER BY RandomValue ASC
I know I can easily achieve that in sql server with Rank operation. I do not see any helpful links to find rank on varchar/text fields. I tried to find rank using the below query. It did not work out.
SELECT
ID,
[Appraiser Name],
(
SELECT COUNT(*)
FROM [Street Data] WHERE
[Appraiser Name] <= T.[Appraiser Name]
) AS Rank
FROM [Street Data] AS T
ORDER BY ID, [Appraiser Name]
Any helps are appreciated.
I solved it some how. But I welcome if there are any easy ways to do it. I created three queries. First one to find the rank of the Appraiser Name, second one to find the distinct of Appraiser Name and third one is the final query. I tried to use the first one in the query with rank = 1 and it gave me join not supported error. That is bad. When I created another query with rank = 1 and then used it in the final one, it worked.
StreetData_Appraiser
SELECT ID, [Appraiser Name], (
SELECT COUNT([Appraiser Name])
FROM [Street Data]
WHERE [Appraiser Name] = T.[Appraiser Name]
AND ID <= T.ID
) AS Rank
FROM [Street Data] AS T
ORDER BY ID, [Appraiser Name]
StreetData_Distinct_Appraiser (Query to mask the first query and show only distinct records and to avoid invalid join error)
SELECT * FROM StreetData_Appraiser WHERE Rank = 1
Final Query
SELECT TOP 400 *
FROM (SELECT ST.*,
Rnd(ST.ID) AS RandomValue
FROM [Street Data] AS ST
INNER JOIN [StreetData_Distinct_Appraiser] AS SA ON SA.ID=ST.ID) AS STRecs
ORDER BY RandomValue

Mysql joining multiple totals - making query efficient

I am creating a clock-in / clock-out system for employees.
There is a tbl_clockins which contains records of each clock-in/clock-out session with information on whether each session is paid, how late the employee was for that session or how much overtime they did, etc.
There is another table called tbl_user_work_settings where the manager can set which days employees are on holiday, or have taken off on sickness etc.
I am creating some reports where I need totals for each employee, e.g. total days taken as holiday by each employee wihin a given date range. I have a very long query which actually gets all the required information, but it is huge and somewhat inefficient. Is there any way to make it smaller/more efficient? Any help is appreciated.
// get total days worked, unpaid days, bank holidays, holidays, sicknesses
// and absences within given date range for given users
$sql = "SELECT us.username, daysWorked, secondsWorked,
unpaidDays, bankHolidays, holidays, sicknesses, absences
FROM
(SELECT username FROM users WHERE clockin_valid='1') us
LEFT JOIN (
SELECT username, selectedDate, count(isUnpaid) AS unpaidDays
FROM tbl_user_work_settings
WHERE isUnpaid = '1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) u ON us.username=u.username
LEFT JOIN (
SELECT username, count(isBankHoliday) AS bankHolidays
FROM tbl_user_work_settings
WHERE isBankHoliday='1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) bh ON us.username=bh.username
LEFT JOIN (
SELECT username, count(isHoliday) AS holidays
FROM tbl_user_work_settings
WHERE isHoliday='1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) h ON us.username=h.username
LEFT JOIN (
SELECT username, count(isSickness) AS sicknesses
FROM tbl_user_work_settings
WHERE isSickness='1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) s ON us.username=s.username
LEFT JOIN (
SELECT username, count(isOtherAbsence) AS absences
FROM tbl_user_work_settings
WHERE isOtherAbsence='1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
) a ON us.username=a.username
LEFT JOIN (
SELECT username, count(DISTINCT DATE(in_time)) AS daysWorked,
SUM(seconds_duration) AS secondsWorked
FROM tbl_clockins
WHERE DATE(in_time)>='$startDate'
AND DATE(in_time)<='$endDate'
GROUP BY username
) dw ON us.username=dw.username";
if(count($selectedUsers)>0)
$sql .= " WHERE (us.username='"
. implode("' OR us.username='", $selectedUsers)."')";
$sql .= " ORDER BY us.username ASC";
You can use SUM(condition) on a single use of the tbl_user_work_settings table:
// get total days worked, unpaid days, bank holidays, holidays, sicknesses
// and absences within given date range for given users
$sql = "
SELECT users.username,
SUM(ws.isUnpaid ='1') AS unpaidDays,
SUM(ws.isBankHoliday ='1') AS bankHolidays,
SUM(ws.isHoliday ='1') AS holidays,
SUM(ws.isSickness ='1') AS sicknesses,
SUM(ws.isOtherAbsence='1') AS absences,
COUNT(DISTINCT DATE(cl.in_time)) AS daysWorked,
SUM(cl.seconds_duration) AS secondsWorked
FROM users
LEFT JOIN tbl_user_work_settings AS ws
ON ws.username = users.username
AND ws.selectedDate BETWEEN '$startDate' AND '$endDate'
LEFT JOIN tbl_clockins AS cl
ON cl.username = users.username
AND DATE(cl.in_time) BETWEEN '$startDate' AND '$endDate'
WHERE users.clockin_valid='1'";
if(count($selectedUsers)>0) $sql .= "
AND users.username IN ('" . implode("','", $selectedUsers) . "')";
$sql .= "
GROUP BY users.username
ORDER BY users.username ASC";
By the way (and perhaps more for the benefit of other readers), I really hope that you are avoiding SQL injection attacks by properly escaping your PHP variables before inserting them into your SQL. Ideally, you shouldn't do that at all, but instead pass such variables to MySQL as the parameters of a prepared statement (which don't get evaluated for SQL): read more about Bobby Tables.
Also, as an aside, why are you handling integer types as strings (by enclosing them in single quote characters)? That's needless and a waste of resource in MySQL having to perform unnecessary type conversion. Indeed, if the various isUnpaid etc. columns are all 0/1, you can change the above to remove the equality test and just use SUM(ws.isUnpaid) etc. directly.
Put each table that would join in a temp table...
then create indexes on joinable fields of temp tables...
and make your query with temp tables.
Example:
SELECT username, selectedDate, count(isUnpaid) AS unpaidDays
INTO #TempTable1
FROM tbl_user_work_settings
WHERE isUnpaid = '1'
AND selectedDate>='$startDate'
AND selectedDate<='$endDate'
GROUP BY username
create clustered index ix1 on #TempTable1 (username)