I've a scenario as below.
I've two tables, and a Common column/Key between the two.
I need Table2 data to be just appended to Table1 without repetition like JOINs.
If there are more rows in one table, other table rows can be NULL.
As shown in figure, Result Table has NULLs when there is no corresponding row count from Table2.
I tried using Joins, but I'm getting a result of 45 rows. But I should get 9 rows.
Thanks in advance.
Edit: Added my queries
SELECT DISTINCT
APPT.PRSN_ID
,APPT.SCHEDULEDAPPOINTMENTS
,APPT.OVERDUEAPPOINTMENTS
,Visit.ENCOUNTER_CATEGORY
,Visit.ENCOUNTER_TYPE
,Visit.ENCOUNTER_DATE
,Visit.ENCOUNTER_FOLLOWUP_DATE
FROM
APPOINTMENTS APPT
OUTER APPLY dbo.fn_GetVisitsOfAPerson(PROV.PRSN_ID) AS Visit
/***********************************************************/
--IN THE ABOVE QUERY, THE FUNCTION IS DEFINED AS BELOW
CREATE FUNCTION dbo.fn_GetVisitsOfAPerson(#PrsnID AS bigint)
RETURNS TABLE
AS
RETURN
(
SELECT
VISITS.PVISITS_PRSN_KEY
,DATA.HE_Category_Description AS 'ENCOUNTER_CATEGORY'
,DATA.HE_Type_Description AS 'ENCOUNTER_TYPE'
,VISITS.PVISITS_DATE AS 'ENCOUNTER_DATE'
,VISITS.PVISITS_FOLLOWUP_DATE AS 'ENCOUNTER_FOLLOWUP_DATE'
FROM
[HS_PRSN_HEALTH_VISITS] VISITS INNER JOIN
[HS_HealthEncounter_Table] DATA ON
ENCOUNTER.PVISITS_CATEGORY = DATA.HE_Category_Code AND
ENCOUNTER.PVISITS_TYPE = DATA.HE_Type_Code
WHERE
PVISITS_PRSN_KEY = #PrsnID
AND PVISITS_VOID = 0
)
GO
I cannot read your data tables, but I think you just need to introduce a row number.
It would be something like this:
select . . .
from (select t1.*, row_number() over (partition by key order by ??) as seqnum
from table1 t1
) full join
(select t2.*, row_number() over (partition by key order by ??) as seqnum
from table1 t2
) t2
on t1.key = t2.key and t1.seqnum = t2.seqnum;
Based on you wanting the 9 rows present in the Visit table it looks like you need an OUTER JOIN, something like:
SELECT DISTINCT
APPT.PRSN_ID
,APPT.SCHEDULEDAPPOINTMENTS
,APPT.OVERDUEAPPOINTMENTS
,Visit.ENCOUNTER_CATEGORY
,Visit.ENCOUNTER_TYPE
,Visit.ENCOUNTER_DATE
,Visit.ENCOUNTER_FOLLOWUP_DATE
FROM Visit
LEFT OUTER JOIN
APPOINTMENTS APPT
ON Visit.key = APP.key
Related
I am trying to build a SQL query to recover only the most young record of a table (it has a Timestamp column already) where the item by which I want to filter appears several times, as shown in my table example:
.
Basically, I have a table1 with Id, Millis, fkName and Price, and a table2 with Id and Name.
In table1, items can appear several times with the same fkName.
What I need to achieve is building up a single query where I can list the last record for every fkName, so that I can get the most actual price for every item.
What I have tried so far is a query with
SELECT DISTINCT [table1].[Millis], [table2].[Name], [table1].[Price]
FROM [table1]
JOIN [table2] ON [table2].[Id] = [table1].[fkName]
ORDER BY [table2].[Name]
But I don't get the correct listing.
Any advice on this? Thanks in advance,
A simple and portable approach to this greatest-n-per-group problem is to filter with a subquery:
select t1.millis, t2.name, t1.price
from table1 t1
inner join table2 t2 on t2.id = t1.fkName
where t1.millis = (select max(t11.millis) from table1 t11 where t11.fkName = t1.fkName)
order by t1.millis desc
using Common Table Expression:
;with [LastPrice] as (
select [Millis], [Price], ROW_NUMBER() over (Partition by [fkName] order by [Millis] desc) rn
from [table1]
)
SELECT DISTINCT [LastPrice].[Millis],[table2].[Name],[LastPrice].[Price]
FROM [LastPrice]
JOIN [table2] ON [table2].[Id] = [LastPrice].[fkName]
WHERE [LastPrice].rn = 1
ORDER BY [table2].[Name]
Hi I have the below query in Teradata. I have a row number partition and from that I want rows with rn=1. Teradata doesn't let me use the row number as a filter in the same query. I know that I can put the below into a subquery with a where rn=1 and it gives me what I need. But the below snippet needs to go into a larger query and I want to simplify it if possible.
Is there a different way of doing this so I get a table with 2 columns - one row per customer with the corresponding fc_id for the latest eff_to_dt?
select cust_grp_id, fc_id, row_number() over (partition by cust_grp_id order by eff_to_dt desc) as rn
from table1
Have you considered using the QUALIFY clause in your query?
SELECT cust_grp_id
, fc_id
FROM table1
QUALIFY ROW_NUMBER()
OVER (PARTITION BY cust_grp_id
ORDER BY eff_to_dt desc)
= 1;
Calculate MAX eff_to_dt for each cust_grp_id and then join result to main table.
SELECT T1.cust_grp_id,
T1.fc_id,
T1.eff_to_dt
FROM Table1 AS T1
JOIN
(SELECT cust_grp_id,
MAX(eff_to_dt) AS max_eff_to_dt
FROM Table
GROUP BY cust_grp_id) AS T2 ON T2.cust_grp_id = T1.cust_grp_id
AND T2.max_eff_to_dt = T1.eff_to_dt
You can use a pair of JOINs to accomplish the same thing:
INNER JOIN My_Table T1 ON <some criteria>
LEFT OUTER JOIN My_Table T2 ON <some criteria> AND T2.eff_to_date > T1.eff_to_date
WHERE
T2.my_id IS NULL
You'll need to sort out the specific criteria for your larger query, but this is effectively JOINing all of the rows (T1), but then excluding any where a later row exists. In the WHERE clause you eliminate these by checking for a NULL value in a column that is NOT NULL (in this case I just assumed some ID value). The only way that would happen is if the LEFT OUTER JOIN on T2 failed to find a match - i.e. no rows later than the one that you want exist.
Also, whether or not the JOIN to T1 is LEFT OUTER or INNER is up to your specific requirements.
I'm trying merging 2 tables as follow
SELECT * FROM T1
LEFT JOIN T2 ON T1.EMPnum = T2.EMPnum
The above works well but I need the joining to use only the first appearance of the common key EMPnum record in table T2 so that the query returns exactly the same number of rows as T1
Thanks Avi
SQL tables are inherently unordered, so there is no such thing as a "first" key. In most databases, you can do something like this:
with t2 as (
select t2.*, row_number() over (partition by EMPnum order by id) as seqnum
from t2
)
select *
from t1 left join
t2
on t1.EMPnum = t2.EMPnum and t2.seqnum = 1;
Here id is just any column that specifies the ordering. If none exist, you can use EMPnum to get an arbitrary row.
I am trying to alter a base query that selects data from several joined tables, and filters out rows based on the CASE WHEN below. The result set is to be returned as follows:
If all of the rows return 0 in the CASE column, return one line with '0' in the OVERDUE column (the "return one line" portion is taken care of by DISTINCT.)
If any of the rows return 1 for the CASE column, return one line with '1' in the OVERDUE column.
The base is as follows:
SELECT DISTINCT t1.*,
CASE WHEN t3.MTemp > t3.MTempLimit
then 1
when t3.TotHours > t3.THoursLimit
then 1
else 0
end [Overdue]
from table_1 t1
LEFT JOIN table_2 t2 on t1.ResNo = t2.ResNo and t1.PCode = t2.PCode
LEFT JOIN table_3 t3 on t2.RepJobNo = t3.RepJobNo
LEFT JOIN table_4 t4 on t4.TypeID = t2.RepType
WHERE t2.RepStat = 1
The catch is, I've already created a working version of this by using a temp table and doing a IF EXISTS/ELSE query on the temp table's OVERDUE column. However, I've been informed that this solution may not be useable (due to having to go through certain front-end software).
Is it possible to do a workaround for this that does not involve using a temporary table? I've been making attempts at using both a derived table and CTEs, neither of which have yielded anything usable, due to the fact that one cannot use IF/ELSE clauses after those (which was what I was counting on).
I'm still getting the hang of T-SQL, so any help would be greatly appreciated.
Sounds like a simple ROW_NUMBER() and a couple of CTEs will work:
;WITH RS1 as (
SELECT t1.*,
CASE WHEN t3.MTemp > t3.MTempLimit
then 1
when t3.TotHours > t3.THoursLimit
then 1
else 0
end [Overdue]
from table_1 t1
LEFT JOIN table_2 t2 on t1.ResNo = t2.ResNo and t1.PCode = t2.PCode
LEFT JOIN table_3 t3 on t2.RepJobNo = t3.RepJobNo
LEFT JOIN table_4 t4 on t4.TypeID = t2.RepType
WHERE t2.RepStat = 1
), RS2 as (
select *,ROW_NUMBER() OVER (ORDER BY Overdue DESC) rn
from RS1
)
select * from RS2 where rn = 1
(There's no need for a DISTINCT now that we're only returning one row)
In general any temporary table referenced in another query can simply be substituted for as follow, so that this:
insert #temp
select -- definition of temptable
;
select ...
from #temp
join ...
becomes
select
from (
-- definition of temptable
) temp
join ...
There are three tables,we have to select data from these table using one primary key and foreign key. But in the one table there is lot of data in the third table. We have to sum the data on the base of the primary key.
BAl = Balance, met = Method, amo = amount, cst_id, cut_id, cut_i = customer_id
Now we have to sum the on the basis of method and sum for 10 cust id in the same query. Can anyone help me on this?
;WITH cte
AS
(
SELECT
*,
ROW_NUMBER() OVER (ORDER BY t1.cst_id) RowNum
FROM Table1 t1
INNER JOIN Table2 t2
ON t1.cst_id = t2.cut_id
INNER JOIN Table3 t3
ON t2.cut_id = t3.customer_id
AND t2.BAL = t3.Balance
AND t2.amo = t3.amount
)
SELECT SUM(*)
FROM cte
WHERE RowNum Between 1 AND 10
-- You can add a GROUP BY here
If you give some sample data it will be easier to write queries to help you.
But if your MET field is numerical and you want to sum it then you need.
select
t1.cst_n, t2.bal,
sum(t3.met) as met,
sum(t3.amo) as amo
from table1 as t1
inner join table2 as t2 on t2.cut_id = t1.cst_id
inner join table3 as t3 on t3.cut_i = t1.cst_id
group by t1.cst_n, t2.bal
well if you want to sum data for all 10 customers into one number, may be you just need
select
sum(t3.met) as met,
sum(t3.amo) as amo
from table3 as t3
where t3.cut_i in (select t.customerid from #<your variable table with cust. ids> as t)