creating a sub-query - sql

Sub-Query Help
I'm having a problem creating a sub-query (I think) and was hoping to get some guidance. Some things have been generalized for simplicity.
Select
A
b
c
d
e
Member ID
Hospital Admit Date
DRG Code
CLM_LN_SVC_FROM_DT
From
Claims Table
Where
DRG Code = 5
And A
And B
And c
I would like to take the result of this query specifically the Member ID and distinct Hospital Admit Dates for the Member and query against the claims table for all claims:
where Member ID in (result from above query) and at this point I need to pull claims in the range 30 days before the admit dates and up to 180 days after the admit date. This is where I'm struggling how to setup this sub query. Any brilliance beyond my limited base would be greatly appreciated...

It sounds you need something similar to following query:
Select Distinct
ClaPeriod.MemberId,
ClaPeriod.DRGCode,
ClaPeriod.ClaimDate,
ClaPeriod.AdmittedDate,
A,
B,
C,
D,
E
From Claims ClaMain,
Claims ClaPeriod
Where (ClaMain.MemberId, ClaMain.AdmittedDate) In (
Select MemberId, AdmittedDate
From Claims claId
Where DRGCode = 5
)
And ClaMain.MemberId = ClaPeriod.MemberId
And ClaPeriod.AdmittedDate >= ClaMain.AdmittedDate - 30
And ClaPeriod.DischargedDate <= ClaMain.AdmittedDate + 180
Order By ClaPeriod.MemberId, ClaPeriod.AdmittedDate
To be honest, I still am not sure I have fully understood your schema. I had to include a Distinct clause in my sql test to avoid duplicate results. If I missed the mark please tell me so and I will try to improve the answer.
UPDATE: Now that the schema is clearer for me as per OP's comments I will try to improve the answer.
As I understand it now, you need to get all claims that:
have the same MBR_ID as a claim with DRG=5.
have an HOSP_ADMT_DT (Admit Date) 30 days prior or before than the CLM_LN_SVC_FROM_DT (From_Date) of the DRG=5 claim.
have an HOSP_DSCHRG_DT (Discharge Date) at least 180 days after the CLM_LN_SVC_FROM_DT (From_Date) of the DRG=5 claim.
If it is so, it can be done with a query that joins the CLM_MED_DETL to itself. ne table would be to filter the claims with DRG=5 and the other to retrieve the claims that have the same MBR_ID and that comply with the date conditions. It would be a query like following:
Select CLAIMS.CLM_MED_DETL_ID,
CLAIMS.CLM_LN_CURR_STAT_TXT,
CLAIMS.CLM_ID_TXT,
CLAIMS.SVCG_PROV_NAME,
CLAIMS.SBMTD_DRG_CD,
CLAIMS.RVNU_CD,
CLAIMS.PLC_OF_SVC_CD,
CLAIMS.CLM_SRC_CD,
CLAIMS.CLM_LN_SEQ_NUM,
CLAIMS.CLM_LN_PRCDR_CD,
CLAIMS.MBR_ID,
CLAIMS.MBR_LST_NAME,
CLAIMS.MBR_FST_NAME,
CLAIMS.SVCG_PROV_ADDR_ZIP_CD,
CLAIMS.SVCG_PROV_ADDR_CNTY,
CLAIMS.HOSP_ADMT_DT,
CLAIMS.HOSP_DSCHRG_DT,
CLAIMS.CLM_LN_UNITS_NUM,
CLAIMS.CLM_LN_CHRG_AMT,
CLAIMS.CLM_LN_ALWD_AMT,
CLAIMS.CLM_LN_PD_AMT,
CLAIMS.TIN_TXT,
CLAIMS.CLM_LN_SVC_FROM_DT,
CLAIMS.CLM_LN_SVC_TO_DT
From CLM_MED_DETL DRG5CLAIMS,
CLM_MED_DETL CLAIMS
Where CLAIMS.MBR_ID = DRG5CLAIMS.MBR_ID
And DRG5CLAIMS.SBMTD_DRG_CD = '005'
And DRG5CLAIMS.CLM_LN_SVC_FROM_DT >= CLAIMS.HOSP_ADMT_DT - 30
And DRG5CLAIMS.CLM_LN_SVC_FROM_DT <= CLAIMS.HOSP_DSCHRG_DT + 180
And CLAIMS.CLM_SRC_CD = 'TRG_FA'
And CLAIMS.CLM_LN_PD_AMT <> 0
And CLAIMS.CLM_LN_CURR_STAT_TXT <> 91
Order By CLAIMS.MBR_LST_NAME Asc, CLAIMS.CLM_LN_SEQ_NUM Asc;

Related

Amazon SQL job interview question: customers who made 2+ purchases -- is it doable in DAX?

You have a simple table that has only two fields: CustomerID, DateOfPurchase. List all customers that made at least 2 purchases in any period of six months. You may assume the table has the data for the last 10 years. Also, there is no PK or unique value.
One possible solution for this question is as follows:
SELECT DISTINCT CustomerID
FROM yourTable t1
WHERE EXISTS (SELECT 1 FROM yourTable t2
WHERE t2.CustomerID = t1.CustomerID AND
t2.DateOfPurchase > t1.DateOfPurchase AND
t2.DateOfPurchase <= DATEADD(month, 6, t1.DateOfPurchase));
I was wondering if we can do something similar in DAX. For the sake of simplicity, let's assume everything is in one table and there is no relationship.
Thanks
You got me at
For the sake of simplicity
Maybe this(?)
Table =
SUMMARIZE(
FILTER(
yourTable,
VAR CurrentCustomerID = yourTable[CustomerID]
VAR CurrentDateOfPurchase = yourTable[DateOfPurchase]
RETURN
NOT ISEMPTY(
CALCULATETABLE(
VALUES(yourTable[CustomerID]),
ALL(yourTable),
yourTable[CustomerID] = CurrentCustomerID,
yourTable[DateOfPurchase] < CurrentDateOfPurchase,
yourTable[DateOfPurchase] >= EDATE(CurrentDateOfPurchase,-6)
)
)
),
yourTable[CustomerID]
)
Update
Since there are no more answers, I am sharing the simulated data so that someone else will be encouraged to respond and we can all learn something from this. Around 50,000 customers, 100,000 transactions, 10 years. Date format: MDY
https://drive.google.com/file/d/1JPS4XHfpGSTXuNWIMdoPlp5Z1BqV9WGO/view?usp=sharing

MS Access SQL Date Range Query

I am working on a classroom reservation tool. A core component is the ability to compare the requested date range to the existing reservations, to ensure that there is no overlap. I've read through several date range related questions here, and studied Salman's explanation and implementation of Allen's interval algebra ( SQL Query to Find Overlapping (Conflicting) Date Ranges ) until I understood it. Here's a stripped-down version of what I came up with.
tblRooms
roomID room
5 110
30 178
tblReservations
reservedID fkRoom dateIn dateOut
1 5 3/10/2017 3/15/2017
2 5 3/1/2017 3/3/2017
4 5 4/1/2017 4/30/2017
SELECT DISTINCTROW tblRooms.roomID, tblRooms.room
FROM tblRooms LEFT JOIN tblReservations
ON tblRooms.roomID = tblReservations.fkRoom
WHERE NOT Exists (
SELECT DISTINCT tblRooms.roomID
FROM tblRooms
WHERE ((tblReservations.[dateOut] >= #3/3/2017#)
AND (#3/9/2017# >= tblReservations.[dateIn])));
I'm getting inconsistent returns. These dates will exclude room 110, as they should. Other test input (#3/4/2017# and #3/10/2017#, #4/1/2017# and #4/14/2017#) won't. I've tried combinations of "WHERE NOT (...", "WHERE Exists () = False", etc.
I work on a highly restrictive network, where I can't pull in templates at will - my only options when I create a database are "Blank" and "Web", so I've got to roll my own on this. I appreciate any assistance.
Can you try the following:
SELECT DISTINCTROW tblRooms.roomID, tblRooms.room
FROM tblRooms
WHERE NOT Exists (
SELECT 1
FROM tblReservations
WHERE
tblReservations.fkRoom = tblRooms.roomID
AND ((tblReservations.[dateOut] >= #3/3/2017#)
AND (#3/9/2017# >= tblReservations.[dateIn])));
For a reservation check query you would do this:
select ...
from tblRooms room
where not exists
( select *
from tblReservations r
where r.fkRoom = room.roomId and
end > r.[datein] and start < r.[dateout] );
BUT the important part is, pass those end and start as parameters instead of hardcoded values like you did. With hardcoded values you are always open to get wrong results or error. For example what is:
#3/9/2017# really? Its interpretation would depend on regional settings (I am not an access programmer so I might be wrong).

How to Avoid Duplicate ID's In Access SQL

I have a problem that I hope you can help me.
I have the next query on Access SQL.
SELECT
ID_PLAN_ACCION, ID_SEGUIMIENTO,
Max(FECHA_SEGUIMIENTO) AS MAX_FECHA
FROM
SEGUIMIENTOS
WHERE
(((ID_PLAN_ACCION) = [CODPA]))
GROUP BY
ID_PLAN_ACCION, ID_SEGUIMIENTO;
And it returns this information:
ID_PLAN_ACCION ID_SEGUIMIENTO MAX_FECHA
-----------------------------------------------
A1-01 1 16/01/2014
A1-01 2 30/01/2014
But I really need that it throws off this:
ID_PLAN_ACCION ID_SEGUIMIENTO MAX_FECHA
----------------------------------------------
A1-01 2 30/01/2014
As you can see I only need the record that has the most recently date, not all the records
The GROUP BY doesn't work.
Please can you tell me what can I do? I am new on all this.
Thank you so much!!
PD: Sorry for my english, I'm learning
This will produce the results you want:
SELECT ID_PLAN_ACCION, max(ID_SEGUIMIENTO) as ID_SEGUIMIENTO, Max(FECHA_SEGUIMIENTO) AS MAX_FECHA
FROM SEGUIMIENTOS
WHERE ID_PLAN_ACCION = [CODPA]
GROUP BY ID_PLAN_ACCION;
I removed id_sequiimiento from the group by and added an aggregation function to get the max value. If the ids increase along with the date, this will work.
Another way to approach this query, though, is to use top and order by:
SELECT top 1 ID_PLAN_ACCION, ID_SEGUIMIENTO, FECHA_SEGUIMIENTO
FROM SEGUIMIENTOS
WHERE ID_PLAN_ACCION = [CODPA]
ORDER BY FECHA_SEGUIMIENTO desc;
This works because you are only returning one row.
EDIT:
If you have more codes, that you are looking at, you need a more complicated query. Here is an approach using where/not exists:
SELECT ID_PLAN_ACCION, ID_SEGUIMIENTO, FECHA_SEGUIMIENTO
FROM SEGUIMIENTOS s
WHERE not exists (select 1
from SEGUIMIENTOS s2
where s.ID_PLAN_ACCION = s2.ID_PLAN_ACCION and
s2.FECHA_SEGUIMIENTO > s.FECHA_SEGUIMIENTO
)
ORDER BY FECHA_SEGUIMIENTO desc;
You can read this as: "Get me all rows from SEGUIMIENTOS where there is no other row with the same ID_PLAN_ACCION that has a larger date". Is is another way of saying that the original row has the maximum date.

Convert a SQL query in Java Persistence Query Language (JPQL)

I'm having a little problem to convert this SQL query to JPQL:
select max(datePurchase) from purchases where userId = id and date_trunc('day',datePurchase)
in (select distinct (date_trunc('day',datePurchase)) as day from purchases where userId = id and datePurchase < initialDate and datePurchase > finalDate) group by date_trunc('day',datePurchase)
This sql is working well, that returns de last purchase per day made from a user. I tried to do the same, in JPQL:
Query query = em.createQuery("SELECT u MAX(u.datePurchase) FROM Purchases u WHERE u.userId.id = :id AND FUNC('day',u.datePurchase)" +
"IN (SELECT DISTINCT (FUNC('day',u.datePurchase)) AS day FROM Purchases WHERE u.userId.id = :id AND u.datePurchase < :finalDate AND u.datePurchase > :inicialDate) GROUP BY FUNC('day',u.datePurchase)");
query.setParameter("id", idUsuario);
query.setParameter("dataInicial", dataInicial);
query.setParameter("dataFinal", dataFinal);
List<MovSaldo> saldos = (List<MovSaldo>) query.getResultList();
em.getTransaction().commit();
The errors are:
"The IN expression does not have a valid expression." "An identification variable must be provided for a range variable declaration."
Probably is not something very difficult, but i have already spent a little frustrating time in it. Can someone please help me?
Although the answer is probably late for you I still posted it because it might help someone in the future.
In the nested select you have to put an identifier for the entity you are working with: FROM Purchases p and update things like (FUNC('day',u.datePurchase)) to (FUNC('day',p.datePurchase))
Best!

Sql query has unwanted results - Where is the problem?

I have a table which records users's scores at a game (a user may submit 5,10,20,as many scores as he wants).
I need to show the 20 top scores of a game, but per user. (as a user may have submitted eg 4 scores which are the top according to other users's scores)
The query i have written is:
SELECT DISTINCT
`table_highscores`.`userkey`,
max(`table_highscores`.`score`),
`table_users`.`username`,
`table_highscores`.`dateachieved`
FROM
`table_highscores`, `table_users`
WHERE
`table_highscores`.`userkey` = `table_users`.`userkey`
AND
`table_highscores`.`gamekey` = $gamekey
GROUP BY
`userkey`
ORDER BY
max(`table_highscores`.`score`) DESC,
LIMIT 0, 20;
The output result is ok, but there is a problem. When i calculate the difference of days (today-this of dateachieved) the result is wrong. (eg instead of saying "the score was submitted 22 days ago, it says 43 days ago) So,I have to do a second query for each score so to find the true date (meaning +20 queries). Is there any shorter way to find the correct date?
Thanks.
there is a problem. When i calculate the difference of days (today-this of dateachieved) the result is wrong.
There's two issues
the dateachieved isn't likely to be the value associated with the high score
you can use MySQL's DATEDIFF to return the the number of days between the current date and the dateachieved value.
Use:
SELECT u.username,
hs.userkey,
hs.score,
DATEDIFF(NOW(), hs.dateachieved)
FROM TABLE_HIGHSCORES hs
JOIN TABLE_USERNAME u ON u.userkey = hs.userkey
JOIN (SELECT ths.userkey,
ths.gamekey,
ths.max_score,
MAX(ths.date_achieved) 'max_date'
FROM TABLE_HIGHSCORES ths
JOIN (SELECT t.userkey,
t.gamekey,
MAX(t.score) 'max_score'
FROM TABLE_HIGHSCORES t
GROUP BY t.userkey, t.gamekey) ms ON ms.userkey = ths.userkey
AND ms.gamekey = ths.gamekey
AND ms.max_score = ths.score
) x ON x.userkey = hs.userkey
AND x.gamekey = hs.gamekey
AND x.max_score = hs.score
AND x.max_date = hs.dateachieved
WHERE hs.gamekey = $gamekey
ORDER BY hs.score DESC
LIMIT 20
I also changed your query to use ANSI-92 JOIN syntax, from ANSI-89 syntax. It's equivalent performance, but it's easier to read, syntax is supported on Oracle/SQL Server/Postgres/etc, and provides consistent LEFT JOIN support.
Another thing - you only need to use backticks when tables and/or column names are MySQL keywords.
In your query you should use an explicit JOIN and you don't need the DISTINCT keyword.
This query should solve your problem. I am assuming here that it is possible for a user to submit the same highscore more than once on different dates, and if that happens then you want the oldest date:
SELECT T1.userkey, T1.score, username, dateachieved FROM (
(SELECT userkey, max(score) AS score
FROM table_highscores
WHERE gamekey = $gamekey
GROUP BY userkey) AS T1
JOIN
(SELECT userkey, score, min(dateachieved) as dateachieved
FROM table_highscores
WHERE gamekey = $gamekey
GROUP BY userkey, score) AS T2
ON T1.userkey = T2.userkey AND T1.score = T2.score
) JOIN table_users ON T1.userkey = table_users.userkey
LIMIT 20
You didn't say what language you are using to calculate the difference but I'm guessing it's PHP because of the $gamekey you used there (which should be escaped properly, btw).
If your dateachieved field is in the DATETIME format, you can calculate the difference like this:
$diff = round((time() - strtotime($row['dateachieved'])) / 86400);
I think you need to clarify your question a little better. Can you provide some data and expected outputs and then I should be able to help you further?