I have 2 queries that work fine by themselves but I've been struggling to get them to work together. I have a table of audits and I am trying to count the audits by auditor. I am using a form to get the date range and the auditor. The auditors are in a table named tblUser. The main table is tblParatransitPullOutAudit. There is a field in this table named AuditId which tells me what Audit each record belongs to. There may be many records with the same Audit ID, these count as 1 audit. I want to count how many audits by date range and Auditor. Any help will be greatly appreciated.
SELECT
t.Contractor,
Count(t.PK_ParapullOut) AS Audits
FROM
tblUser
INNER JOIN
tblParatransitPullOutAudit AS t
ON tblUser.PK_User = t.Auditor
WHERE ((t.AuditDate) Between forms!frmTotalAuditsDateRangeAuditor!txbStartDate.value And forms!frmTotalAuditsDateRangeAuditor!txbEndDate.value)
And ((tblUser.PK_User)=Forms!frmTotalAuditsDateRangeAuditor!cboAuditor.value)
GROUP BY Contractor;
SELECT
p.Contractor,
Count(p.AuditID) AS Audits
FROM
(
SELECT DISTINCT
p.Auditor,
p.AuditDate,
p.contractor,
p.auditid
FROM tblParatransitPullOutAudit AS p
) AS Total
WHERE ((p.AuditDate) Between forms!frmTotalAuditsDateRange!txbStartDate.value And forms!frmTotalAuditsDateRange!txbEndDate.value)
GROUP BY p.Contractor;
Related
I have two tables as below:
User: User_ID, User_name and some other columns (has approx 1000 rows)
Fee: Created_By_User_ID, Created_Date and many other columns (has 17 million records)
Fee table does not have any index (and I can't create one).
I need a list of users for each month of a year (say 2016) who have created at least one fee record.
I do have a working query below which is taking long time to execute. Can someone help me with a better query? May be using EXIST clause (I tried one but still takes time as it scans Fee table)
SELECT MONTH(f.Created_Date), f.Created_By_User_ID
FROM Fees f
JOIN [User] u ON f.Created_By_User_ID= u.User_ID
WHERE f.Created_Date BETWEEN '2016-01-01' AND '2016-12-31'
You will require a full scan of the fee table once in the original query you are using. If you use just the join directly, as you have in the original query, you will require multiple scans of the fee table, many of which will go through redundant rows while the join occurs. Same scenario will occur when you use an inner query as suggested by Mansoor.
An optimization could be to decrease the number of rows on which the joins are happening.
Assuming that the user table contains only one record per user and the Fee table has multiple records per person, we can attempt to find distinct months users made a purchase for by using a CTE.
Then we can make a join on top of this CTE, this will reduce the computation performed by the join and should give a slightly better output time when performing over a large data set.
Try this:
WITH CTE_UserMonthwiseFeeRecords AS
(
SELECT DISTINCT Created_By_User_ID, MONTH(Created_Date) AS FeeMonth
FROM Fee
WHERE Created_Date BETWEEN '2016-01-01' AND '2016-12-31'
)
SELECT User_name, FeeMonth
FROM CTE_UserMonthwiseFeeRecords f
INNER JOIN [User] u ON f.Created_By_User_ID= u.User_ID
Also, you have not mentioned that you require the user names and all, if only id is required for the purpose of finding distinct users making purchases per month, then you can just use the query within the CTE and not even require the JOIN as:
SELECT DISTINCT Created_By_User_ID, MONTH(Created_Date) AS FeeMonth
FROM Fee
WHERE Created_Date BETWEEN '2016-01-01' AND '2016-12-31'
Try below query :
SELECT MONTH(f.Created_Date), f.Created_By_User_ID
FROM Fees f
WHERE EXISTS(SELECT 1 FROM [User] u WHERE f.Created_By_User_ID= u.User_ID
AND DATEDIFF(DAY,f.Created_Date,'2016-01-01') <= 0 AND
DATEDIFF(DAY,f.Created_Date,'2016-12-31') >= 0
You may try this approach to reduce the query run time. however, It does duplicate the huge data and store a instance of table (Temp_Fees), On every DML performed on table Fees/User require truncate and fresh load of table Temp_Fees.
Select * into Temp_Fees from (SELECT MONTH(f.Created_Date) as Created_MONTH, f.Created_By_User_ID
FROM Fees f
WHERE f.Created_Date BETWEEN '2016-01-01' AND '2016-12-31' )
SELECT f.Created_MONTH, f.Created_By_User_ID
FROM Temp_Fees f
JOIN [User] u ON f.Created_By_User_ID= u.User_ID
Medical records in my Crystal Report are sorted in this order:
...
Group 1: Score [Level of Risk]
Group 2: Patient Name
...
Because patients are sorted by Score before Name, the report pulls in multiple entries per patient with varying scores - and since duplicate entries are not always adjacent, I can't use Previous or Next to suppress them. To fix this, I'd like to only display the latest entry for each patient based on the Assessment Date field - while maintaining the above order.
I'm convinced this behavior can be implemented with a custom SQL command to only pull in the latest entry per patient, but have had no success creating that behavior myself. How can I accomplish this compound sort?
Current SQL Statement in use:
SELECT "EpisodeSummary"."PatientID",
"EpisodeSummary"."Patient_Name",
"EpisodeSummary"."Program_Value"
"RiskRating"."Rating_Period",
"RiskRating"."Assessment_Date",
"RiskRating"."Episode_Number",
"RiskRating"."PatientID",
"Facility"."Provider_Name",
FROM (
"SYSTEM"."EpisodeSummary"
"EpisodeSummary"
LEFT OUTER JOIN "FOOBARSYSTEM"."RiskAssessment" "RiskRating"
ON (
("EpisodeSummary"."Episode_Number"="RiskRating"."Episode_Number")
AND
("EpisodeSummary"."FacilityID"="RiskRating"."FacilityID")
)
AND
("EpisodeSummary"."PatientID"="RiskRating"."PatientID")
), "SYSTEM"."Facility" "Facility"
WHERE (
"EpisodeSummary"."FacilityID"="Facility"."FacilityID"
)
AND "RiskRating"."PatientID" IS NOT NULL
ORDER BY "EpisodeSummary"."Program_Value"
The SQL code below may not be exactly correct, depending on the structure of your tables. The code below assumes the 'duplicate risk scores' were coming from the RiskAssessment table. If this is not correct, the code may need to be altered.
Essentially, we create a derived table and create a row_number for each record, based on the patientID and ordered by the assessment date - The most recent date will have the lowest number (1). Then, on the join, we restrict the resultset to only select record #1 (each patient has its own rank #1).
If this doesn't work, let me know and provide some table details -- Should the Facility table be the starting point? are there multiple entries in EpisodeSummary per patient? thanks!
SELECT es.PatientID
,es.Patient_Name
,es.Program_Value
,rrd.Rating_Period
,rrd.Assessment_Date
,rrd.Episode_Number
,rrd.PatientID
,f.Provider_Name
FROM SYSTEM.EpisodeSummary es
LEFT JOIN (
--Derived Table retreiving highest risk score for each patient)
SELECT PatientID
,Assessment_Date
,Episode_Number
,FacilityID
,Rating_Period
,ROW_NUMBER() OVER (
PARTITION BY PatientID ORDER BY Assessment_Date DESC
) AS RN -- This code generates a row number for each record. The count is restarted for every patientID and the count starts at the most recent date.
FROM RiskAssessment
) rrd
ON es.patientID = rrd.patientid
AND es.episode_number = rrd.episode_number
AND es.facilityid = rrd.facilityid
AND rrd.RN = 1 --This only retrieves one record per patient (the most recent date) from the riskassessment table
INNER JOIN SYSTEM.Facility f
ON es.facilityid = f.facilityid
WHERE rrd.PatientID IS NOT NULL
ORDER BY es.Program_Value
Learning SQL so please forgive me.
I have a table that holds many accounts(and sub accounts) and another table that holds many orders they are custom tables taken from different databases.
What I am trying to do is update order_amt on the account table with the order_val value from the orders table but if there are more than one order with that account I want the order amount from the earliest order date only.
Account Table
Acc _Num..........Comp_Name.......Order_Amt.......Int_Id
123456789-1.....ABC Ltd.......................................123456789
123456789-2.....ABC Ltd.......................................123456789
987654321-1.....Xyz Ltd.........................................987654321
987654321-2.....Xyz Ltd.........................................987654321
Orders Table
Order_Num.....Order_Dt.....Order_Val.....Acc_num
1......................01/01/13......£20.00...........123456789
2......................01/01/14......£10.00...........123456789
3......................01/01/10......£100.00..........987654321
4......................01/01/11......£200.00..........987654321
So the order_amt for accounts 123456789-1 & 2 = £20.00 and from 987654321-1 & 2 would be £100.00.
UPDATE accounts a
SET a.order_amt =
(
SELECT order_val
FROM orders o
WHERE a.int_id = o.acc_num
AND EXISTS
(
SELECT MIN(order_dt)
FROM orders oa
WHERE o.order_num = oa.order_num
);
I am getting a few errors including the error that more than one row returned? Could anyone please help me?
kind Regards
Eden
I think you need something like this:
UPDATE accounts a
SET a.order_amt =
(
SELECT order_val
FROM orders o
WHERE a.int_id = o.acc_num
GROUP BY order_val
HAVING order_dt = MIN(order_dt);
);
Create a FK on the column account_number inside of the orders table and have it reference the auto-increment account id of the accounts table.
Then as Roger suggest, with the slight modification of the column int_id AND a modification of the HAVING clause
UPDATE accounts a
SET a.order_amount =
(
SELECT order_value
FROM orders o
WHERE a.account_number = o.account_number
GROUP BY order_value
HAVING MIN(order_date)
)
This will not fix the error that is occurring with more than one row being returned though since there are multiple orders with the same account id attached to them. You will need to be more specific about how what you are needing. Do you want the average of all order amounts to equal the order value in the accounts table? Or maybe the MAX/MIN value?
I create a new view in SQL Server 2008 from two tables that have relation on a field. I want to create a report and do grouping on that common field.
For example:
table1: student(ID,first-name,last-name,phone,address,...)
table2: courses(ID,fk_ID,Course,....)
Now I want to have report that shows all data from both tables with grouping on ID from student table, that must show courses information separated for every student.
my query is:
SELECT TOP (100) PERCENT
dbo.tbl_student.ID,
dbo.tbl_student.firstname, dbo.tbl_student.lastname,
dbo.tbl_courses.Coursename,
dbo.tbl_Courses.CourseDate, dbo.tbl_courses.coursetype,
FROM
dbo.tbl_student LEFT OUTER JOIN
dbo.tbl_courses ON dbo.tbl_student.ID = dbo.tbl_courses.fk_id
ORDER BY
dbo.tbl_student.firstname DESC
But when I create a new report from this view, it shows just one record for every group. I spent 2 hours to solve the problem but I did not succeed.
please help me to create report from two or more tables.
Now it shows one record duplicates for several times for every group
Have you tried a query like this:
SELECT s.[ID], s.[first-name], s.[last-name], s.[phone], ...
c.[ID], c.[Course], ...
FROM student s
LEFT OUTER JOIN
courses c ON s.[ID] = c.[fk_ID]
I would like to add a calculated field to many of my tables and will be able to use this new technique many times.
I have sub records such as values for SalePrice and I would like to have these totals show in an employees record.
I would appreciate a sample query and how to implement considering the following data:
Table 1 (Employees): ID, EmployeeName, [Calculated Field]
Table 2 (Sales): ID, InventoryItem, SalePrice, QuantityOrdered
I would like to fetch [SalePrice] x [QuantityOrdered] in 2 scenarios:
Total Sales to date
Total Sales within a date range (where these 2 values can be entered
on a form) for administration purposes as our employees are paid
commission only.
I'm used to adding table fields in both Layout and Design view.
Kind regards, Mikey.
This should get you started: MS Access SQL: http://office.microsoft.com/en-nz/access-help/access-sql-basic-concepts-vocabulary-and-syntax-HA010256402.aspx. Calculated fields in queries: http://office.microsoft.com/en-nz/access-help/create-a-calculated-field-in-a-query-mdb-HP005188023.aspx.