Display fields from temp table in select - sql

I have the following SQL. The problem is that it only displays results in the output for the the following : wp.gtid, wp.first_name etc I want to display the results from wpe.gtid, wpe.first_name etc too. So that i can see easily a comparison of the fields side by side.
with dups as (
select
wp.GtId
from CORE.WeccoParty wp
where exists (select 1
from CORE.WeccoParty wpe
-- where wp.Tin = wpe.Tin
where wp.FirstName = wpe.LastName
and wp.GtId <> wpe.GtId
)
)
select distinct
wp.GtId,
wp.CrmPartyId,
wp.LegalName,
wp.BusinessClass,
wp.RmFullName,
wp.PbeFullName,
wp.OverallClientStatus,
wp.OverallRpStatus,
wp.FirstName,
wp.LastName,
wp.Tin
from CORE.WeccoParty wp
join dups d on d.GtId = wp.GtId
order by 1,2

K1205, when I checked your code it seems to identify duplicate entries having the same FirstName but different GtId values
So maybe you can use Row_Number() function with partition by clause
Could you please check following SQL?
select
ROW_NUMBER() over (Partition By wp.FirstName Order By wp.GtId) as rn,
wp.GtId,
wp.CrmPartyId,
wp.LegalName,
wp.BusinessClass,
wp.RmFullName,
wp.PbeFullName,
wp.OverallClientStatus,
wp.OverallRpStatus,
wp.FirstName,
wp.LastName,
wp.Tin
from CORE.WeccoParty wp
order by wp.FirstName, rn
I hope following CTE query helps you for solution
The data (firstname and gtid) from duplicates are added as new columns after the first entry for the same firstname
with rawdata as (
select
ROW_NUMBER() over (Partition By wp.FirstName Order By wp.GtId) as rn,
wp.GtId,
wp.CrmPartyId,
wp.LegalName,
wp.BusinessClass,
wp.RmFullName,
wp.PbeFullName,
wp.OverallClientStatus,
wp.OverallRpStatus,
wp.FirstName,
wp.LastName,
wp.Tin
from WeccoParty wp
)
select t1.*, t2.GtId, t2.FirstName
from rawdata as t1
inner join rawdata as t2
on t1.FirstName = t2.FirstName and
t1.rn <> t2.rn
where t1.rn = 1
order by t1.FirstName, t2.rn

Related

Remove multiple rows with same ID

So I've done some looking around and wasn't unable to find quite what I was looking for. I have two tables.
1.) Table where general user information is stored
2.) Where a status is generated and stored.
The problem is, is that there are multiple rows for the same users and querying these results in multiple returns. I can't just merge them because they aren't all the same status. I need just the newest status from that table.
Example of the table:
SELECT DISTINCT
TOP(50) cam.UserID AS PatientID,
mppi.DisplayName AS Surgeon,
ISNULL(sci.IOPStatus, 'N/A') AS Status,
tkstat.TrackerStatusID AS Stat_2
FROM
Main AS cam
INNER JOIN
Providers AS rap
ON cam.VisitID = rap.VisitID
INNER JOIN
ProviderInfo AS mppi
ON rap.UnvUserID = mppi.UnvUserID
LEFT OUTER JOIN
Inop AS sci
ON cam.CwsID = sci.CwsID
LEFT OUTER JOIN
TrackerStatus AS tkstat
ON cam.CwsID = tkstat.CwsID
WHERE
(
cam.Location_ID IN
(
'SURG'
)
)
AND
(
rap.IsAttending = 'Y'
)
AND
(
cam.DateTime BETWEEN CONCAT(CAST(GETDATE() AS DATE), ' 00:00:00') AND CONCAT(CAST(GETDATE() AS DATE), ' 23:59:59')
)
AND
(
cam.Status_StatusID != 'Cancelled'
)
ORDER BY
cam.UserID ASC
So I need to grab only the newest Stat_2 from each ID so they aren't returning multiple rows. Each Stat_2 also has an update time meaning I can sort by the time/date that column is : StatusDateTime
One way to handle this is to create a calculated row_number for the table where you need the newest record.
Easiest way to do that is to change your TKSTAT join to a derived table with the row_number calculation and then add a constraint to your join where the RN =1
SELECT DISTINCT TOP (50)
cam.UserID AS PatientID, mppi.DisplayName AS Surgeon, ISNULL(sci.IOPStatus, 'N/A') AS Status, tkstat.TrackerStatusID AS Stat_2
FROM Main AS cam
INNER JOIN Providers AS rap ON cam.VisitID = rap.VisitID
INNER JOIN ProviderInfo AS mppi ON rap.UnvUserID = mppi.UnvUserID
LEFT OUTER JOIN Inop AS sci ON cam.CwsID = sci.CwsID
LEFT OUTER JOIN (SELECT tk.CwsID, tk.TrackerStatusId, ROW_NUMBER() OVER (PARTITION BY tk.cwsId ORDER BY tk.CreationDate DESC) AS rn FROM TrackerStatus tk)AS tkstat ON cam.CwsID = tkstat.CwsID
AND tkstat.rn = 1
WHERE (cam.Location_ID IN ( 'SURG' )) AND (rap.IsAttending = 'Y')
AND (cam.DateTime BETWEEN CONCAT(CAST(GETDATE() AS DATE), ' 00:00:00') AND CONCAT(CAST(GETDATE() AS DATE), ' 23:59:59'))
AND (cam.Status_StatusID != 'Cancelled')
ORDER BY cam.UserID ASC;
Note you need a way to derive what the "newest" status is; I assume there is a created_date or something; you'll need to enter the correct colum name
ROW_NUMBER() OVER (PARTITION BY tk.cwsId ORDER BY tk.CreationDate DESC) AS rn
SQL Server doesn't offer a FIRST function, but you can reproduce the functionality with ROW_NUMBER() like this:
With Qry1 (
Select <other columns>,
ROW_NUMBER() OVER(
PARTITION BY <group by columns>
ORDER BY <time stamp column*> DESC
) As Seq
From <the rest of your select statement>
)
Select *
From Qry1
Where Seq = 1
* for the "newest" record.

Why do I get ORA-00907 in my SQL query?

I have this SQL query which a partner has done for a little project at university (this is the first time we use SQL), but we get the ora-00907 error and both of us don't know why.
I have checked the parenthesis and they seem to be ok, so the problem must be another.
select
persona.nombre,
anyo,
t2.total
from persona join
(
select
t1.idPersona,
count(produccion.anyo) as total,
anyo
from
(
select *
from produccion
join pelicula
on produccion.id = pelicula.id
) as pel
join
(
select *
from participa
where idPapel = 8
) as t1
on t1.idProduccion = pel.id
)
group by t1.idPersona
) as t2
on persona.id = t2.idPersona
where t2.total > 2
order by t2.total desc;
You are selecting * and doing group by on one column which is creating problem. Either you select only respective column under group by condition OR you remove group by.
select *
from (produccion join pelicula on produccion.id=pelicula.id) as pel
join
(select *
from participa
where idPapel=8) as t1
on t1.idProduccion=pel.id)
group by t1.idPersona
Above code section is unallowed use of group by.
If group by is so much needed, i would suggest you to use it later on in the end. Another option is to use analytical function and filter out rest un-wanted records in upper nesting of query which you already have.
You have lots of nested views, which makes your query rather hard to debug. You have lots of brackets, which need to match.
Anyway this is wrong: select t1.idPersona, count(produccion.anyo) as total, anyo. You'll need to include anyo in the GROUP BY clause, which will probably change the result set you want.
select persona.nombre,
t2.anyo,
t2.total
from persona join
(select t1.idPersona,
count(produccion.anyo) as total,
anyo
from (select *
from produccion
join pelicula
on produccion.id=pelicula.id) pel
join
(select *
from participa
where idPapel=8) t1
on t1.idProduccion=pel.id
group by t1.idPersona, t1.anyo) t2
on persona.id=t2.idPersona
where t2.total>2
order by t2.total desc;
I think your query can be simplified/corrected like this:
select persona.nombre,
anyo,
t2.total
from persona
join (
select par.idPersona,
count(produccion.anyo) as total,
anyo
from produccion
join pelicula
on produccion.id = pelicula.id
left join participa par
on par.idProduccion = pelicula.id -- or produccion.id,
-- this was also an error in the original query,
-- since the subquery selected both
and par.idPapel = 8
group by t1.idPersona
, anyo -- Was missing, but it also doesn't make sense, as this is what you count, so you'll just get 1's here. What do you want with this?
) as t2
on persona.id = t2.idPersona
where t2.total > 2
order by t2.total desc;

Table alias name scope in sub-select query

Please have a look at the query below - I am getting invalid identifier t1.oid in the below inner query.
I have column oid in iclr_request t1
select t1.requestNo
, t2.routeDistance,
, (
select WM_CONCAT(crc7) as "TravCirc7s"
from (
select (
select crc7
from dim_afi_dnld_stn_v1
where stn_sys_nbr = t3.stn_sys_nbr
and rownum=1
) as crc7
from iclr_trav_circ7 t3
where request_oid = **t1.oid**
and sub_route_index=0
and station_type_oid = 1
order by sequence
)
)
from iclr_request t1
, iclr_summary_results t2
where t1.oid = t2.request_oid
You can try this:
select t1.requestNo , t2.routeDistance,
WM_CONCAT((select crc7 from dim_afi_dnld_stn_v1 where stn_sys_nbr = t3.stn_sys_nbr and rownum=1)) as "TravCirc7s"
from iclr_request t1
join iclr_summary_results t2 on t1.oid = t2.request_oid
left join iclr_trav_circ7 t3 on t3.request_oid = t1.oid
and t3.sub_route_index=0
and t3.station_type_oid = 1
group by t1.requestNo , t2.routeDistance;
Correlated subqueries may refer their parents only 1 level above (although some Oracle documentation says it's unlimited)
EDIT: It doesn't save the order by sequence in WM_CONCAT. You may need to wrap it a parent query and then wm_concat

sql query - update fields in existing with record values in the same table

Environment: SQL Server 2012
I have a transaction table that contains a group of records with group id column.
In the example illustrated below, group 2 records were copied from group 1 records, Except for the sideId, sideSort, topId and topSort columns. Is there a way to cascade that down from group 1 to group 2 for just topSort and sideSort? The hard part is that topId and sideId aren't the same because of Identity fields in parent tables.
Here is a sqlfiddle of the example
You can do it this way. This is based on the assumption that you copy all the records for one group (#copiedFromGroupId) to another (#copiedToGroupId), i.e. that the ID's will be shifted by the number of records in the first group.
declare #copiedFromGroupId int = 1
declare #copiedToGroupId int = 2
declare #shift int
select #shift = (select max(id) from Tracker where GroupId = #copiedToGroupId)
- (select max(id) from Tracker where GroupId = #copiedFromGroupId)
UPDATE T1
SET
T1.TopSort = T2.TopSort,
T1.SideSort = T2.SideSort
FROM Tracker T1
INNER JOIN Tracker T2 ON T1.ID = T2.ID + #shift
Check this SQL Fiddle
This is based on the row_number over the ORDER of TopId and SortID columns:
update test
set test.topSort = mix.topSort, test.sideSort = mix.sideSort
from
(select a.groupid aGroupid, b.groupID, b.Id bID, a.topSort, a.sideSort
from (select groupid,
row_number() over(order by topID, sideId) rn,
topSort, sideSort,
id
from test where groupid=1) a
inner join
(select groupid,
row_number() over(order by topID, sideId) rn,
topSort, sideSort,
id
from test where groupid=2) b ON a.rn = b.rn) mix
inner join test on test.id=mix.bId
WHERE test.groupid=2;
SQLFiddle
Assuming that Id is an order field in the Group:
WITH C as
(
select Tracker.*,
ROW_NUMBER() OVER (PARTITION BY GroupId ORDER BY Id) as RN
FROM Tracker
)
UPDATE CT
SET CT.topSort=CTU.topSort,
CT.sideSort=CTU.sideSort
FROM C as CT
JOIN C as CTU ON (CT.rn=CTU.rn)
and (CTU.GroupID=1)
WHERE CT.GroupID=2
SQLFiddle demo

Return top 3 rows per group

When I made this select it shows as result all “rut” with it phone numbers, my problem
is that each “rut” has almost 10 phone numbers, and I need just 3 phone numbers for
each “rut”, I tryied using TOP, but just shows the first 3 rows of all table and not the
first rows by “rut”, how can I use TOP just for the row “rut” and not in the all the
table
Select Distinct
t1.rut_cliente as rut_cliente,
t1.nro_fono as numero
--Into #tmp_numeros
From dat_clientes_sucursales_contactos_telefonos t1,dat_rut_clientes t2
where t1.rut_cliente = t2.rut_cliente
and cod_prioridad = 1
this is what I get with this query:
Rut_cliente Nro_fono
60506000-5 2046840
60506000-5 3507935
60506000-5 4106886
60506000-5 5440000
60506000-5 5445000
81698900-0 2373281
81698900-0 3541342
81698900-0 3541438
81698900-0 3541518
81698900-0 3542101
and this is what I want:
Rut_cliente Nro_fono
60506000-5 2046840
60506000-5 3507935
60506000-5 4106886
81698900-0 2373281
81698900-0 3541342
81698900-0 3541438
thanks in advance.
The question was originally tagged SQL Server 2008, where you can do this using a common table expression:
;WITH x AS
(
SELECT Rut_cliente, Nro_fono, rn = ROW_NUMBER()
OVER (PARTITION BY Rut_cliente ORDER BY Nro_fono)
FROM dbo.dat_clientes_sucursales_contactos_telefonos AS t1
INNER JOIN dbo.dat_rut_clientes AS t2
ON t1.rut_cliente = t2.rut_cliente
WHERE cod_prioridad = 1
)
SELECT Rut_cliente, Nro_fono FROM x
WHERE rn <= 3
ORDER BY Rut_cliente, Nro_fono;
Other comments:
Please don't use table, table syntax. Use proper INNER JOINs. I explain why here.
Please add proper aliases to the inner query, so people know which columns come from t1 and which columns come from t2.
But now we learn the user is actually using SQL Server 2000. This is how I would do it there, I think, but performance is going to be horrible. I'm not 100% sure this works (because again I'm making guesses about which columns come from which table).
SELECT x.rut_cliente, x.nro_fono, COUNT(*) FROM
(
SELECT t1.rut_cliente, t1.nro_fono
FROM dat_clientes_sucursales_contactos_telefonos AS t1
INNER JOIN dat_rut_clientes AS t2
ON t1.rut_cliente = t2.rut_cliente
WHERE cod_prioridad = 1
) AS x
INNER JOIN dat_clientes_sucursales_contactos_telefonos AS b
ON b.rut_cliente = x.rut_cliente
AND b.nro_fono <= x.nro_fono
GROUP BY x.rut_cliente, x.nro_fono
HAVING COUNT(*) <= 3
ORDER BY x.rut_cliente, x.Nro_fono;
For example with ROW_NUMBER which is a window function and returns a row-number for each partition(similar to group by) determined by the order by.:
WITH CTE AS(
SELECT t1.rut_cliente as rut_cliente, t1.nro_fono as numero,
RN = ROW_NUMBER()OVER(PARTITION BY Rut_cliente ORDER BY Nro_fono)
FROM dbo.dat_clientes_sucursales_contactos_telefonos AS t1
INNER JOIN dbo.dat_rut_clientes AS t2 ON t1.rut_cliente = t2.rut_cliente
WHERE cod_prioridad = 1
)
SELECT rut_cliente as rut_cliente, nro_fono as numero
FROM CTE
WHERE RN <= 3
Try this
;with CTE AS (
select Rut_cliente, Nro_fono , ROW_NUMBER() OVER
(PARTITION BY Rut_cliente ORDER BY Nro_fono) rn
FROM dbo.dat_clientes_sucursales_contactos_telefonos AS a
INNER JOIN dbo.dat_rut_clientes AS b
ON a.rut_cliente = b.rut_cliente
WHERE cod_prioridad = 1
)
SELECT * FROM CTE where rn <=3