Looking to select only first of set - mysql

In my query I am able to successfully extract the mass data, however it would be very helpful if I am able to drill down to only selecting the first project start date of the data set.
I've tried adding a (MIN) to my query but it errors out, any suggestions ?
For clarification, I am looking to select the first project start date on a particular contract. Any contract can have (n) # of projects. My goal is to detect the first of them.
Here is my query :
SELECT DISTINCT CONT.CONTRACTNUMBER as "Contract Number",
CS.PRODUCTID as "Product ID",
PROJ.PROJECTID as "Project ID",
PR.PRODDESCRIPTION as "Product Description",
PROJ.PROJECTNAME as "Project Name",
CS.STARTDT as "Contract Service/ Product Start DT",
CONT.CONTRACTStartDT as "Contract Start DT",
PROJ.PROJECTSTARTDT as "Project Start DT",
Datediff(DAY, CS.STARTDT, PROJ.PROJECTSTARTDT) as "# Day Difference"
FROM PRODUCTDATA.DBO.HHCONTRACTSERVICE CS WITH(NOLOCK)
LEFT OUTER JOIN COSTTRACKERDATA.DBO.OAPROJECT PROJ WITH(NOLOCK)
ON CS.DID = PROJ.EXTERNALID
LEFT OUTER JOIN PRODUCTDATA.DBO.HHCONTRACT CONT WITH(NOLOCK)
ON CS.CONTRACTDID = CONT.DID
LEFT OUTER JOIN FIGURES..DIMPRODUCT PR WITH(NOLOCK)
ON CS.PRODUCTID = PR.PRODUCTID
AND PR.SUBPRODUCTLINE IN ( 'S', 'S' )
WHERE CS.STARTDT BETWEEN '2020-01-01' AND '2021-11-11'
AND PROJ.PROJECTSTARTDT <> '1970-01-01 00:00:00.000'
order by [Contract Number], [Project Start DT]

First in the list or the earliest date in the list?
either way you can order your list the way you want and add limit 1 at the end. That will give you the first row only.
The LIMIT clause is used in the SELECT statement to constrain the number of rows to return.
https://www.mysqltutorial.org/mysql-limit.aspx

Related

SQL match between two tables and further match between columns

I have two tables: Master Data and Sample Data.
Master Data has columns "Key", "from date", "to date", "PayTM"
Sample Data has columns "Key", "creation date", "PayTS"
I'm trying to get the code to do this:
For every "key" match between two tables >
Determine if "creation date" falls between "from date" and "to date" >
IF YES, show that match/record (from Sample Data table) including PayTM and PayTS.
IF NO, dont show the record. (And go through all of the matches performing steps 2 and 3)
This is what I have so far, but it's showing records that don't match...I tried replacing WHERE NOT EXISTS with EXISTS but it's giving me an error. My sql coding skills are very basic and I'm struggling with trying to make the code work past this for some reason.
SELECT cd.*
FROM [Sample Data] as cd
WHERE NOT EXISTS (SELECT 1
FROM [Master Data] as md
WHERE cd.Key = md.Key AND
md.[Creation Date] BETWEEN md.From Date and md.To Date
);
Your problem can be solved by simple join. Something like:
SELECT cd.* , md.*
FROM [Sample Data] as cd, [Master Data] as md
WHERE cd.Key = md.Key AND
cd.[Creation Date] BETWEEN md.[From Date] and md.[To Date];
Note: The above query is pseudo query just to high-light idea.
I think this should handle it.
select
x.key_
,x.paytm
,x.payts
from(
select
md.key as key_
,cd.paytm as paytm
,cd.payts as payts
,case when md.creation_date between md.from_date and md.to_date
then 'goodie'
else 'baddie'
end as the_test
from
[master data] md
inner join
[sample data] cd
on cd.key = md.key
)x
where
x.the_test != 'baddie'

Display 0 for rows with no data

The Query below displays records for 5 Dashboards. The query works fine. But it displays only those Dashboards for which data exists. What I want to do is, it should display all the Dashboards and the columns for which data does not exist, it should display 0 or NULL.
Select
b.[path],
count(*) as "No of Calls",
a.TimeDataRetrieval as "DB Retrieval time",
a.TimeProcessing as "Processing time",
a.TimeRendering as "Rendering Time"
FROM LogStorage a inner join Catalog b on a.[ReportID] = b.[ItemID]
where b.[path] IN ('Dashboard1','Dashboard2','Dashboard3','Dashboard4','Dashboard5')
group by b.[path]
Thanks.
The key part is:
FROM LogStorage a inner join Catalog b on a.[ReportID] = b.[ItemID]
where b.[path] IN ('Dashboard1','Dashboard2','Dashboard3','Dashboard4','Dashboard5')
This is restricting the result set to only records that exist in LogStorage and Catalog, irrespective of the join type.
You want to flip this around and use a left-join:
SELECT b.[path]
, SUM (CASE WHEN a.some_column IS NULL THEN 0 ELSE 1 END) as "No of Calls"
, a.TimeDataRetrieval as "DB Retrieval time"
, a.TimeProcessing as "Processing time"
, a.TimeRendering as "Rendering Time"
FROM Catalog b
LEFT JOIN LogStorage a on b.[ItemID] = a.[ReportID]
WHERE b.[path] IN ('Dashboard1','Dashboard2','Dashboard3','Dashboard4','Dashboard5')
group by b.[path]
, a.TimeDataRetrieval
, a.TimeProcessing
, a.TimeRendering
Also, for which table are you counting records? It's a little ambiguous, although if I had to guess I'd say LogStorage. In that case you'll probably want to aggregate those other LogStorage columns, as without an aggregate the output will be just be the rows and the count will be 1 for each row.
Edit: I forgot to mention, that COUNT probably needs to be a SUM CASE expression because null values are eliminated with an aggregate like this.

Graded Assignment [Zaption] Database

Most specifically, I'm having trouble returning from LibreOffice Base [HSQLdb] a list of grades organized by (1) class, (2) assignment, (3) student's last name.
I want this output so I can run a script to copy the grades from the database to an online gradebook (which doesn't have an API [sadface])
I suspect several possible causes for this problem:
My relational structure may need tweaking.
I somehow need to implement a "student ID." On Zaption, Students make their submissions under whatever "ZaptionName" they choose to use. I then manually match ZaptionName to RosterFullName in the second table shown.
Zaption allows multiple submissions by the same "student" for the same assignment. Because multiple submissions are allowed, I run a FilterLowMultiples query to select the highest grade for that assignment for that student.
FilterLowMultiples:
SELECT MAX( "Grade" ) "Grade", "RosterFullName",
"Assignment", MAX( "ZaptionName" ) "ZapName"
FROM "SelectAssignment"
GROUP BY "RosterFullName", "Assignment"
SelectAssignment is below for reference:
SELECT "GradedAssignments"."Assignment", "Roster"."RosterFullName",
"GradedAssignments"."Grade", "ZaptionNames"."ZaptionName"
FROM "Roster", "ClassIndex", "GradedAssignments", "ZaptionNames"
WHERE "Roster"."Class" = "ClassIndex"."Class"
AND "GradedAssignments"."ZaptionName" = "ZaptionNames"."ZaptionName"
AND "ZaptionNames"."RosterFullName" = "Roster"."RosterFullName"
AND ( "GradedAssignments"."Assignment" = 'YouKnowWhatever')
My query to PullAssignmentGrades is as follows, but sorting by assignment fails, as there is no assignment by default unless that student submitted one, so the row is blank and that student falls to the bottom of the sort, which is bad for the transfer-to-online script I run.
SELECT "Roster"."RosterFirstName", "ClassIndex"."Class",
"Roster"."RosterFullName", "ClassIndex"."ClassLevel",
"FilterLowMultiples"."Grade", "FilterLowMultiples"."ZapName",
"FilterLowMultiples"."Assignment", "FilterLowMultiples"."Grade",
"FilterLowMultiples"."Assignment", "ClassIndex"."ClassDisplayOrder",
"Roster"."RosterLastName"
FROM "ClassIndex", "FilterLowMultiples", "Roster"
ORDER BY "Roster"."RosterFirstName" ASC,
"FilterLowMultiples"."Grade" DESC,
"FilterLowMultiples"."Assignment" ASC,
"ClassIndex"."ClassDisplayOrder" ASC,
"Roster"."RosterLastName" ASC
Use a LEFT JOIN in your query for SelectAssignment so you don't drop students who didn't do a particular assignment. Optionally you can use COALESCE on the potentially NULL values from the "GradedAssignments" table to assign a grade of 0 or I. Like so:
SELECT 'YouKnowWhatever' AS "Assignment", "Roster"."RosterFullName",
COALESCE("GradedAssignments"."Grade",0), "ZaptionNames"."ZaptionName"
FROM "Roster"
INNER JOIN "ClassIndex" ON "Roster"."Class" = "ClassIndex"."Class"
INNER JOIN "ZaptionNames" ON "ZaptionNames"."RosterFullName" = "Roster"."RosterFullName"
LEFT JOIN "GradedAssignments" ON ("GradedAssignments"."ZaptionName" = "ZaptionNames"."ZaptionName"
AND "GradedAssignments"."Assignment" = 'YouKnowWhatever')

SQL Server 2008 - select based on query results

I am currently working with this query
SELECT DISTINCT
se.src_aet AS "Ripped By",
CONVERT(varchar(32), s.created_time, 113) AS "Date/Time Sent",
p.pat_name AS "Patient Name",
p.pat_id AS "Patient ID",
s.accession_no AS "ACC #",
p.pat_birthdate AS "DOB",
s.mods_in_study AS "MOD",
CONVERT(varchar(32), s.study_datetime, 113) AS "Study Date",
s.study_desc AS "Study Desc",
s.study_custom1 AS "Inst Name"
FROM
dbo.patient AS p
INNER JOIN
dbo.study AS s ON s.patient_fk = p.pk
INNER JOIN
dbo.series AS se ON se.study_fk = s.pk
WHERE
accession_no like '%OUT%'
AND s.created_time >= CAST(getdate() as DATE)
AND s.created_time < CAST(DATEADD(day, 1, getdate()) as DATE)
ORDER BY
"Date/Time Sent" DESC
In the above example, it comes back with:
RIPPED BY DATE/TIME SENT PATIENT NAME PATIENT ID ACC# DOB
BC 18 Aug 2014 12:58:44:297 DOE^JOHN^^^ HOSP1234 OUT 19510101
I have taken the last few columns away (in the above example output) for simplicity sake here.
It is working correctly. It comes back with a list of studies that have the word 'OUT' in the accession_no column and that have been written to the DB 'today'.
What I am wanting to return are all of the unique values for 'pat_id' in the dbo.patient table for those found in the query. Some of those patients found the query above might already exist in the dbo.patient table if they have been to our site before, but they will have a different 'pat_id'.
What I want the output to look like is:
RIPPED BY DATE/TIME SENT PATIENT NAME PATIENT ID_OUT PATIENT ID_EXIST ACC# DOB STUDY DATE STUDY DESC INST NAME
the column 'PATIENT ID_OUT' is the patient ID that would be on the study that has the value of 'OUT' in the accession_no column and the column 'PATIENT ID_EXIST' is the existing patient ID, if it does exist. The value for 'PATIENT ID_EXIST' may be blank in some cases if the patient is new.
I was thinking I was needing to do a sub-query here, but maybe that is not the right thing to do in this case? Correct me if I am wrong.
EDIT: I have provided an example of the output. I am trying to figure out if the patient in the output has a different 'Patient ID' based on searching for the pat_name and pat_dob in the query results. If there is another or more than one patient ID in the pat_id column, then I would like them in the output.
I hope this is clear :)
I usually tackle tasks like this by treating the query as a table and joining to it.
SELECT p.*
FROM dbo.patient p
INNER JOIN (your big query) q
ON q.pat_id = p.pat_id

MS Access query multiple criteria

I am trying to build an access query with multiple criteria. The table to be queried is "tblVendor" which has information about vendor shipment data as shown below:
The second table is "tblSchedule" which has the schedule for each Vendor cutoff date. This table has cutoff dates for data analysis.
For each vendor, I need to select records which have the ShipDate >= CutoffDate. Although not shown in the data here, it may be possible that multiple vendors have same CutoffDate.
For small number of records in "tblCutoffdate", I can write a query which looks like:
SELECT tblVendors.ShipmentId, tblVendors.VendorNumber, tblVendors.VendorName,
tblVendors.Units, tblVendors.ShipDate
FROM tblVendors INNER JOIN tblCutoffDate ON tblVendors.VendorNumber =
tblCutoffDate.VendorNumber
WHERE (((tblVendors.VendorNumber) In (SELECT VendorNumber FROM [tblCutoffDate] WHERE
[tblCutoffDate].[CutoffDate] = #2/1/2014#)) AND ((tblVendors.ShipDate)>=#2/1/2014#)) OR
(((tblVendors.VendorNumber) In (SELECT VendorNumber FROM [tblCutoffDate] WHERE
[tblCutoffDate].[CutoffDate] = #4/1/2014#)) AND ((tblVendors.ShipDate)>=#4/1/2014#));
As desired, the query gives me a result which looks like:
What concerns me now is that I have a lot of records being added to the "tblCutoffDate" which makes it difficult for me to hardcode the dates in the query. Is there a better way to write the above SQL statement without any hardcoding?
You might try something like -- this should handle vendors having no past cutoff,
or those having no future cutoff
"today" needs a suitable conversion to just date w/o time
comparison "=" may go on both, or one, or none Max/Min
"null" may be replaced by 1/1/1900 and 12/31/3999 in Max/Min
SELECT tblvendors.shipmentid,
tblvendors.vendornumber,
tblvendors.vendorname,
tblvendors.units,
tblvendors.shipdate
FROM tblvendors
LEFT JOIN
( SELECT vendornum,
Max( iif cutoffdate < today, cutoffdate, null) as PriorCutoff,
Min( iif cutoffdate >= today, cutoffdate, null) as NextCutoff
FROM tblcutoffdate
GROUP BY vendornum
) as VDates
ON vendornumber = vendornum
WHERE tblvendors.shipdate BETWEEN PriorCutoff and NextCutoff
ORDER BY vendornumber, shipdate, shipmentid
A simpler WHERE clause should give you what you want.
SELECT
v.ShipmentId,
v.VendorNumber,
v.VendorName,
v.Units,
v.ShipDate
FROM
tblVendors AS v
INNER JOIN tblCutoffDate AS cd
ON v.VendorNumber = cd.VendorNumber
WHERE v.ShipDate >= cd.CutoffDate;