Select records even if doesn't exists - sql

I have database with 4 tables:
First table represents rooms and has single column called "RoomNumber".
Second table is Hours and has single column "HourNumber".
Third table is Days and has two columns "DayNumber" and "DayName".
Last table is TimeTables of rooms and it's a relation table between the three other tables.
The last table has the following columns:
RoomNumber
DayNumber
HourNumber
Subject (what's happening at the specific hour and day)
but this table stores only records with rooms that has Subject (it keep only busy hours of rooms), it doesn't presents records with empty subjects so it can't show me when a chosen room is available (no subject means the room is clear).
I want to somehow write a query that will give me the status of all the rooms in a specific day and hour.
For example this query returns all the busy rooms at day 1, hour 1:
SELECT *
FROM TimeTables
WHERE HourNumber = 1 AND DayNumber = 1
But I want to get the status of all the rooms at the specific time, I know the rest of the records doesn't exists.
Is there a way to do something like that?

If you want the status of the rooms in MS Access, I think a correlated subquery is the simplest method:
select r.*,
(select tt.subject
from TimeTables as tt
where tt.RoomNumber = r.RoomNumber and tt.HourNumber = 1 and tt.DayNumber = 1
) as subject_1_1
from rooms as r;

Related

How to compare value in where clause with max value for an ID?

I am trying to make a selection from a lot of different tables, and for one of the constraints the primary key can not have an item associated to it that has a date within the last 30 days. However, it is possible for the primary key to have multiple items associated with it.
The issue that i currently face is when there are multiple items associated, one that is within the date range and one that is outside, it is still getting returned. I want it to be excluded if any of the associated item's dates are within the past 30 days.
How can i make the program to fetch all the items instead of just one at a time?
Thanks!
Using NOT IN
select *
from table
where id not in (select id from table where datefield > dateadd(day,-30,getdate())
This only returns records from the table where the id doesn't have a record where the datefield is more than 30 days old. You likely need a join too since you reference a lot of different tables. Something like...
select *
from table
where id not in (select id
from table
inner join table2 on table2.refid = table.id
where table2.datefield > dateadd(day,-30,getdate())

SQL - select IDs that have been seen in table w/ timestamp <= 1+ year

I have a table with user IDs, timestamps, and sales info. The same user IDs appear multiple times in the data (every time they purchase). I only want to select the user IDs that have shown up in the table for at least a year (so, for the sake of simplicity I'll do a timestamp less than "12-31-2016"). How can I write this with SQL?
Try this:
Select Distinct userID
FROM Table
WHERE DATEDIFF(yy,cast(Timestamp as date),getdate())>=1
Updated based on your comment:
Select Distinct userID
FROM Table
WHERE CAST(Timestamp as date)>'20161231'

Suppress Nonadjacent Duplicates in Report

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

Select average rating from another datatable

I have 3 data tables.
In the entries data table I have entries with ID (entryId as primary key).
I have another table called EntryUsersRatings in there are multiple entries that have entryId field and a rating value (from 1 to 5).
(ratings are stored multiple times for one entryId).
Columns: ratingId (primary key), entryId, rating (integer value).
In the third data table I have translations of entries in the first table (with entryId, languageId and title - translation).
What I would like to do is select all entries from first data table with their titles (by language ID).
On a top of that I want average rating of each entry (which can be stored multiple times) that is stored in EntryUsersRatings.
I have tried this:
SELECT entries.entryId, EntryTranslations.title, AVG(EntryUsersRatings.rating) AS AverageRating
FROM entries
LEFT OUTER JOIN
EntryTranslations ON entries.entryId = EntryTranslations.entryId AND EntryTranslations.languageId = 1
LEFT OUTER JOIN
EntryUsersRatings ON entries.entryId = EntryUsersRatings.entryId
WHERE entries.isDraft=0
GROUP BY title, entries.entryId
isDraft is just something that means that entries are not stored with all information needed (just incomplete data - irrelevant for our case here).
Any help would be greatly appreciated.
EDIT: my solution gives me null values for rating.
Edit1: this query is working perfectly OK, I was looking into wrong database.
We also came to another solution, which gives us the same result (I hope someone will find this useful):
SELECT entries.entryId, COALESCE(x.EntryUsersRatings, 0) as averageRating
FROM entries
LEFT JOIN(
SELECT rr.entryId, AVG(rating) AS entryRating
FROM EntryUsersRatings rr
GROUP BY rr.entryId) x ON x.entryId = entries.entryId
#CyberHawk: as you are using left outer join with entries, your result will give all records from left table and matching record with your join condition from right table. but for unmatching records it will give you a null value .
check out following link for the deta:
http://msdn.microsoft.com/en-us/library/ms187518(v=sql.105).aspx

Using a query to update existing records.

Basically, I have a table of data with plenty of records (10,000+)
They all have 4 fields in common which must have data entered. The unique data is TIME.
I have already done a group sort query which has identified the group's of data based on these 4 fields, and then calculated an average time for each group.
I'm now needing to re-insert the average time against the real time in a table so each individual record's time can be evaluated against the average of its type.
For instance, one group from the query would have the result
Process1, Week2, Operator3, Shift4, AvgOfTIME = 120.70
It would then need to re-insert that average time into all records that match those criteria, but do it for every group result and record.
Is this even possible?
you need to update table use subquery
update t1 set t1.timefield = s2.AvgOfTIME
from yourtable t1
inner join
(
-- you query for calculating avg time
)
as t2
on t1.Process1 = t2.Process1 and t1.Week2 = t2.Week2 and t1.Operator3 = t2.Operator3 and t1.Shift4 = t2.Shift4