SQL match between two tables and further match between columns - mysql

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'

Related

Looking to select only first of set

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

Query to find entries and transpose

I've got a machine log available in an SQL table. I can do a bit in SQL, but I'm not good enough to process the following:
In the data column there are entries containing "RUNPGM: Recipe name" and "RUNBRKPGM: Recipe name"
What I want is a view containing 4 columns:
TimeStamp RUNPGM
TimeStamp RUNBRKPGM
Recipe Name
Time Difference in seconds
There is a bit of a catch:
Sometimes the machine logs an empty RUNBRKPGM that should be ignored
The RUNBRKPGM is sometimes logged with an error message. This entry should also be ignored.
It's always the RUNBRKPGM entry with just the recipe name that's the actual end of the recipe.
NOTE: I understand this is not a full/complete answer, but with info available in question as of now, I believe it at least helps give a starting point since this is too complicated (and formatted) to put in the comments:
If Recipe is everything in the DATA field except the 'RUNPGM = ' part you can do somethign similar to this:
SELECT
-- will give you a col for TimeStamp for records with RUNPGM
CASE WHEN DATA LIKE 'RUNPGM%' THEN TS ELSE '' END AS RUNPGM_TimeStamp,
-- will give you a col for TimeStamp for records with RUNBRKPGM
CASE WHEN DATA LIKE 'RUNBRKPGM%' THEN TS ELSE '' END AS RUNBRKPGM_TimeStamp,
-- will give you everything after the RUNPGM = (which I think is the recipe you are referring to)
CASE WHEN DATA LIKE 'RUNPGM%' THEN REPLACE(DATA, 'RUNPGM = ', '' AS RUNPGM_Recipe,
-- will give you everything after the RUNBRKPGM = (which I think is the recipe you are referring to)
CASE WHEN DATA LIKE 'RUNBRKPGM:%' THEN REPLACE(DATA, 'RUNBRKPGM = ', '' AS RUNPGM_Recipe
FROM TableName
Im not sure what columns you want to get the Time Difference on though so I dont have that column in here.
Then if you need to do additional logic/formatting on the columns once they are separated you can put the above in a sub select.
As a first swing, I'd try the following:
Create a view that uses string splitting to break the DATA column into a its parts (e.g. RunType and RecipeName)
Create a simple select that outputs the recipe name and tstamp where the runtype is RUNPGM.
Then add an OUTER APPLY:
Essentially, joining onto itself.
SELECT
t1.RecipeName,
t1.TimeStamp AS Start,
t2.TimeStamp AS Stop
--date func to get run time, pseudo DATEDIFF(xx,t1.TimeStamp, t2.TimeStamp) as RunTime
FROM newView t1
OUTER APPLY ( SELECT TOP ( 1 ) *
FROM newView x
WHERE x.RecipeName = t1.RecipeName
AND RunType = 'RUNBRKPGM'
ORDER BY ID DESC ) t2
WHERE t1.RunType = 'RUNPGM';

How can I enter an Alias and Have all "" in this Field?

I'm using SQL Server. I'm trying to enter an Alias field, as a placeholder (haven't received this data yet), and I keep getting an error. Please see the image bellow.
I'm not sure how to set this up in SQL Server, but in Access it would simply be like this:
Any idea how I can make this work?
Thanks to all.
Here is the SQL Script:
SELECT dbo.Plan_ID_Mapping.[Level 3 Service], dbo.Plan_ID_Mapping.[PLAN ID],
dbo.All_Enteprise_NONProduction_and_Production_Hardware.Application_Systems_Software_ID_CI_ID AS CI_ID,
dbo.All_Enteprise_NONProduction_and_Production_Hardware.Application_Systems_Software_Name_CI_Name AS CI_Name,
dbo.All_Enteprise_NONProduction_and_Production_Hardware.Description_Product_Name, dbo.Service_Taxonomy.[Critical Y/N],
dbo.Service_Taxonomy.[Criticality Rationale], dbo.qry_BE.BE, dbo.qry_BE.Street, dbo.qry_BE.City, dbo.qry_BE.ST, dbo.qry_BE.Zip, dbo.qry_BE.Country,
dbo.qry_BE.O_L, dbo.qry_BE.ENTITY, dbo.qry_BE.Comp_Code
FROM dbo.Plan_ID_Mapping INNER JOIN
dbo.All_Enteprise_NONProduction_and_Production_Hardware ON
dbo.Plan_ID_Mapping.[PLAN ID] = dbo.All_Enteprise_NONProduction_and_Production_Hardware.Plan_Id INNER JOIN
dbo.LocationWorkSpaceByPlanWithAllIn ON
dbo.All_Enteprise_NONProduction_and_Production_Hardware.Plan_Id = dbo.LocationWorkSpaceByPlanWithAllIn.Plan_Id INNER JOIN
dbo.qry_BE ON dbo.LocationWorkSpaceByPlanWithAllIn.Location_ID = dbo.qry_BE.BE INNER JOIN
dbo.Service_Taxonomy ON dbo.Plan_ID_Mapping.[Level 3 Service] = dbo.Service_Taxonomy.[Level 3]
GROUP BY dbo.Plan_ID_Mapping.[Level 3 Service], dbo.All_Enteprise_NONProduction_and_Production_Hardware.Application_Systems_Software_ID_CI_ID,
dbo.All_Enteprise_NONProduction_and_Production_Hardware.Application_Systems_Software_Name_CI_Name, dbo.Plan_ID_Mapping.[PLAN ID],
dbo.All_Enteprise_NONProduction_and_Production_Hardware.Description_Product_Name, dbo.Service_Taxonomy.[Critical Y/N],
dbo.Service_Taxonomy.[Criticality Rationale], dbo.qry_BE.BE, dbo.qry_BE.Street, dbo.qry_BE.City, dbo.qry_BE.ST, dbo.qry_BE.Zip, dbo.qry_BE.Country,
dbo.qry_BE.O_L, dbo.qry_BE.ENTITY, dbo.qry_BE.Comp_Code
Quick Answer:
Uncheck the GROUP BY for PACKAGE_ID
EXPLANATION
It looks like PACKAGE_ID is the the alias column you are creating. Which, if there is nothing there, you can't group on it. I rewrote your query below using table alias for clarity and commented out what it really would look like. What is happening is since you don't have anything for PACKAGE_ID the SQL statement literally would reflect:
SELECT NULL AS PACKAGE_ID
Your error lies in trying to group on theLITERAL of NULL. You can't group on a literal. For example the query below wouldn't work since we are attempting to group on the literal 2007. In order to make it work, we'd have to remove the 2007 from the grouping.
SELECT
COLUMN1,
COLUMN2,
2007
FROM
TABLE1
GROUP BY
COLUMN1,
COLUMN2,
2007
YOUR CODE
SELECT
map.[Level 3 Service],
map.[PLAN ID],
eh.Application_Systems_Software_ID_CI_ID AS CI_ID,
eh.Application_Systems_Software_Name_CI_Name AS CI_Name,
eh.Description_Product_Name,
tax.[Critical Y/N],
tax.[Criticality Rationale],
qry.BE,
qry.Street,
qry.City,
qry.ST,
qry.Zip,
qry.Country,
qry.O_L,
qry.ENTITY,
qry.Comp_Code,
NULL as PACKAGE_ID --this is your blank alias field you created
FROM
dbo.Plan_ID_Mapping map
INNER JOIN
dbo.All_Enteprise_NONProduction_and_Production_Hardware eh ON
map.[PLAN ID] = eh.Plan_Id
INNER JOIN
dbo.LocationWorkSpaceByPlanWithAllIn loc ON
eh.Plan_Id = loc.Plan_Id
INNER JOIN
dbo.qry_BE qry ON
loc.Location_ID =qry.BE
INNER JOIN
dbo.Service_Taxonomy tax ON
map.[Level 3 Service] = tax.[Level 3]
GROUP BY
map.[Level 3 Service],
eh.Application_Systems_Software_ID_CI_ID,
eh.Application_Systems_Software_Name_CI_Name,
map.[PLAN ID],
eh.Description_Product_Name,
tax.[Critical Y/N],
tax.[Criticality Rationale],
qry.BE,
qry.Street,
qry.City,
qry.ST,
qry.Zip,
qry.Country,
qry.O_L,
qry.ENTITY,
qry.Comp_Code,
NULL --This is your query trying to group on the blank field

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

How do you format dates within MS Access Queries to prevent the US/UK issue

How do I ensure that I pick up the right number of records when filtering for dates within an Access Query:
SELECT ID, REF, SalesDate, DCount("ID","tblRecords"," Ref='" & [Ref] & "' AND [SalesDate]=#" & format([SalesDate],"yyyy/mm/dd") & "#") as EXPR1 from tblCurrent
It picks up the date ok if it cannot be misconstrued such as 28-04-12, but if it is 04-06-12 it doesn't pick it up as it's assuming it's the wrong way around.
Note that this query is not created on the fly or generated from a form etc...
I either use yyyy/mm/dd for dates in VBA:
#" & Format([SalesDate],"yyyy/mm/dd") & "#"
Or parameters, for building queries.
EDIT re additional information
Seeing you are using SQL server, I suggest you use a derived table, which you may find faster, for example:
SELECT dbo_Table_1.ADate, ACount FROM dbo_Table_1
LEFT JOIN (SELECT a.ADate,Count(*) As ACount
FROM dbo_Table_1 As a GROUP BY a.ADate) b
ON dbo_Table_1.Adate=b.ADate
EDIT re discussion
SELECT * FROM dbo_vwRecordsCurrent As t
LEFT JOIN (
SELECT a.OpptyIncentiveModifiedDate, a.DataSetID, Count(*) AS ACount
FROM dbo_vwRecordsHistorical AS a
WHERE a.OpportunityIgnored = True
GROUP BY a.OpptyIncentiveModifiedDate, a.DataSetID) AS h
ON t.OpptyIncentiveModifiedDate = h.OpptyIncentiveModifiedDate
AND t.DataSetID = h.DataSetID
I have aliased your tables as the names are very long, so to me, it is more readable to use aliases on the outer sql. They are essential in the inner sql. It is not a good idea to alias a derived table with the name of an existing table.