SQL server query for pulling data from child table - sql

I have a table called Identifier which has identifierType, identifierValue and foreignkey to patient table.
One patient can have multiple identifiers so for a given patient there will be multiple rows in identifier table.
I want to pull value of patientforeign key from this table which meets given criteria,
one example is I want to find
patientId where identifierType = 'PatientFirst"
and identifierValue = 'sally'
and identifierType= 'patientFirst'
and identifier value = 'sally'.
what will be sql statement to pull this result in sqlserver
References : ( http://sqlfiddle.com/#!3/33fc6/2/0 )

Seems a bit easy for this website, no? :)
SELECT fk_patientID
FROM identifier
WHERE IdentifierType = 'PatientFirst'
AND IdentifierValue = 'sally'

Pivot table may be useful to you as well if you'd like to flatten certain properties into a single row per patient ID:
;with PatientFullName( fk_patientId, PatientLast, PatientFirst )
as
(
select
fk_patientId
, pt.PatientLast
, pt.PatientFirst
from
Identifier
pivot
(
MAX(identifierValue)
for identifierType in ( [PatientLast], [PatientFirst] )
) as pt
)
select
*
from
PatientFullName pfn
where
pfn.PatientLast = 'Doe'
and pfn.PatientFirst = 'Sally'

Related

How to execute a select with a WHERE using a not-always-existing column

Simple example: I have some (nearly) identical tables with personal data (age, name, weight, ...)
Now I have a simple, but long SELECT to find missing data:
Select ID
from personal_data_a
where
born is null
or age < 1
or weight > 500
or (name is 'John' and surname is 'Doe')
Now the problem is:
I have some personal_data tables where the column "surname" does not exit, but I want to use the same SQL-statement for all of them. So I have to check (inside the WHERE clause) that the last OR-condition is only used "IF the column surname exists".
Can it be done in a simple way?
You should have all people in the same table.
If you can't do that for some reason, consider creating a view. Something like this:
CREATE OR REPLACE VIEW v_personal_data
AS
SELECT id,
born,
name,
surname,
age,
weight
FROM personal_data_a
UNION ALL
SELECT id,
born,
name,
NULL AS surname, --> this table doesn't contain surname
age,
weight
FROM personal_data_b;
and then
SELECT id
FROM v_personal_data
WHERE born IS NULL
OR age < 1
OR ( name = 'John'
AND ( surname = 'Doe'
OR surname IS NULL))
Can it be done in a simple way?
No, SQL statements work with static columns and the statements will raise an exception if you try to refer to a column that does not exist.
You will either:
need to have a different query for tables with the surname column and those without;
have to check in the data dictionary whether the table has the column or not and then use dynamic SQL to build your query; or
to build a VIEW of the tables which do not have that column and add the column to the view (or add a GENERATED surname column with a NULL value to the tables that are missing it) and use that instead.
While dynamic predicates are usually best handled by the application or by custom PL/SQL objects that use dynamic SQL, you can solve this problem with a single SQL statement using DBMS_XMLGEN, XMLTABLE, and the data dictionary. The following code is not what I would call "simple", but it is simple in the sense that it does not require any schema changes.
--Get the ID column from a PERSONAL table.
--
--#4: Get the IDs from the XMLType.
select id
from
(
--#3: Convert the XML to an XMLType.
select xmltype(personal_xml) personal_xmltype
from
(
--#2: Convert the SQL to XML.
select dbms_xmlgen.getxml(v_sql) personal_xml
from
(
--#1: Use data dictionary to create SQL statement that may or may not include
-- the surname predicate.
select max(replace(replace(
q'[
Select ID
from #TABLE_NAME#
where
born is null
or age < 1
or weight > 500
or (name = 'John' #OPTIONAL_SURNAME_PREDICATE#)
]'
, '#TABLE_NAME#', table_name)
, '#OPTIONAL_SURNAME_PREDICATE#', case when column_name = 'SURNAME' then
'and surname = ''Doe''' else null end)) v_sql
from all_tab_columns
--Change this literal to the desired table.
where table_name = 'PERSONAL_DATA_A'
)
)
where personal_xml is not null
)
cross join xmltable
(
'/ROWSET/ROW'
passing personal_xmltype
columns
id number path 'ID'
);
See this db<>fiddle for a runnable example.

Oracle SQL - Looking to execute Outer query for each row returned by inner query

This is my first ever question :
Below is what I am trying to execute :
update SRM_SR_AuditLog
set MODIFIED_DATE = '1426816800'
, USER_X = 'Vaibhav via DB'
where REQUEST_ID in (
select max(REQUEST_ID) from SRM_SR_AuditLog
where ORIGINAL_REQUEST_ID = (
select SYSREQUESTID from SRM_Request
where REQUEST_NUMBER in (
'ASREQ0000136770', 'ASREQ0000137758', 'ASREQ0000138174',
'ASREQ0000138175', 'ASREQ0000138176', 'ASREQ0000138177',
'ASREQ0000138178', 'ASREQ0000138180', 'ASREQ0000138181',
'ASREQ0000138238', 'ASREQ0000138319', 'ASREQ0000138349',
'ASREQ0000139486', 'ASREQ0000140292', 'ASREQ0000140295',
'ASREQ0000140299', 'ASREQ0000140334', 'ASREQ0000140403',
'ASREQ0000140637', 'ASREQ0000140692' )
)
);
I know below wouldnt work :
ORIGINAL_REQUEST_ID = (
select SYSREQUESTID from SRM_Request where REQUEST_NUMBER in
Because query (select SYSREQUESTID from SRM_Request** where REQUEST_NUMBER = "XYZ") will return more one records but for each of that record in SRM_Request there are more than one records in table "SRM_SR_AuditLog". I want the latest/biggest request id reference from "SRM_ST_Audit" table for each of the SYSREQUESTID returned by above query.
Hope this makes sense.
I want to execute outer query for each value returned by inner query.
How can I proceed on this please ?
Thanks heaps
Vab
If I am understanding correctly, then I think what you want is this:
update SRM_SR_AuditLog set
MODIFIED_DATE = '1426816800',
USER_X = 'Vaibhav via DB' where
REQUEST_ID in
(
select max(REQUEST_ID) from SRM_SR_AuditLog where
ORIGINAL_REQUEST_ID IN
(
select SYSREQUESTID from SRM_Request where REQUEST_NUMBER in
(
'ASREQ0000136770', 'ASREQ0000137758', 'ASREQ0000138174', 'ASREQ0000138175', 'ASREQ0000138176', 'ASREQ0000138177', 'ASREQ0000138178', 'ASREQ0000138180', 'ASREQ0000138181', 'ASREQ0000138238', 'ASREQ0000138319', 'ASREQ0000138349', 'ASREQ0000139486', 'ASREQ0000140292', 'ASREQ0000140295', 'ASREQ0000140299', 'ASREQ0000140334', 'ASREQ0000140403', 'ASREQ0000140637', 'ASREQ0000140692'
)
)
group by ORIGINAL_REQUEST_ID
)
This will find all request IDs in SRM_Request for the given request numbers; find all rows in SRM_SR_AuditLog whose original request ID is in those request IDs; find the maximum region ID for each unique original request ID; and update the rows with those request IDs.
Thanks for the reply Dave.
SRM_Request has one to many mapping with SRM_SR_AuditLog table.
updating to "IN" will scan all records and find just one record with max(REQUEST_ID).
select SYSREQUESTID from SRM_Request where REQUEST_NUMBER in
(
'ASREQ0000136770', 'ASREQ0000137758', 'ASREQ0000138174', 'ASREQ0000138175', 'ASREQ0000138176', 'ASREQ0000138177', 'ASREQ0000138178', 'ASREQ0000138180', 'ASREQ0000138181', 'ASREQ0000138238', 'ASREQ0000138319', 'ASREQ0000138349', 'ASREQ0000139486', 'ASREQ0000140292', 'ASREQ0000140295', 'ASREQ0000140299', 'ASREQ0000140334', 'ASREQ0000140403', 'ASREQ0000140637', 'ASREQ0000140692'
)
This will return 20 references
for each of these 20 references - I want 20 references from SRM_SR_AuditLog via max(REQUEST_ID).
"select max(REQUEST_ID) from SRM_SR_AuditLog where "
"IN" or "=" wouldnt help.

SQL - Create table from Select + user defined columns and values

Currently I have the following SELECT statement:
CREATE TABLE TEST AS
SELECT ROW_ID,
PROM_INTEG_ID,
INTEGRATION_ID,
BILL_ACCNT_ID,
SERV_ACCT_ID,
CFG_STATE_CD
FROM PRODUCTS
WHERE PROD_ID = 'TestProduct'
AND STATUS_CD = 'Active';
However I have to add some additional columns which do not exist in the PRODUCTS table and define them with my own name .e.g HIERARCHY
I tried using the WITH operand in my SQL query but it keeps failing as the syntax is wrong.
CREATE TABLE TEST AS
SELECT ROW_ID,
PROM_INTEG_ID,
INTEGRATION_ID,
BILL_ACCNT_ID,
SERV_ACCT_ID,
CFG_STATE_CD
WITH
PRODUCT_HEIRARCHY varchar2(30) 'Test123Value'
FROM PRODUCT
WHERE PROD_ID = 'TestProduct'
AND STATUS_CD = 'Active';
So in summary, I want to pull in columns from an existing table as well as defining some of my own.
Any help appreciated
Just add the columns to the select:
CREATE TABLE TEST AS
SELECT ROW_ID, PROM_INTEG_ID, INTEGRATION_ID, BILL_ACCNT_ID, SERV_ACCT_ID, CFG_STATE_CD,
CAST('Test123Value' AS VARCHAR2(30)) as PRODUCT_HIERARCHY
FROM PRODUCTS
WHERE PROD_ID = 'TestProduct' AND STATUS_CD = 'Active';
Note that the cast() is not necessary. But it is a good idea if you want the column to have a specific type.
Also using CTE i.e. WITH clause as known commonly, you could create table.
CREATE TABLE t
AS
WITH data AS (
SELECT...
)
SELECT *
FROM data

ORACLE SQL issue

I have requirement like in address table I have address of many people stored but the address of a particular person can change.but address table is insert only.Every time address of a particular person changes we insert a new row and change the address in that row and we have one common_id column in the table which tells for which person this address got changed.So for each change in particular row the new row is added having same common_id as original initial row.I wrote the query for getting the latest address(finding by time_created) whose status is N and type L for all the people.But it is failing
select *
from address wi
where type = 'L'
and status = 'N'
and time_created = (
select time_created
from (
select *
from address w1
where wi.common_id = w1.common_id
order by time_created desc
) t
where rownum = 1
)
the above query is failing but when I am writing below query it is passing and giving the expected result
select *
from address wi
where type = 'L'
and status = 'N'
and time_created = (
select max(time_created)
from address t
where t.common_id = wi.common_id
)
the above query is passing and giving the expected result.
I am amazed why why previous query is failing giving ora-00904 invalid identifier wi.common_id.Kindly help in understanding.
Your problem is that you are trying to make a correlation two levels down, and you can only do it in one level. That's why your second query works, and the first won't. As it doesn't recognize wi.common_id anymore, because you are doing two nested subqueries to find the latest date.
...
and time_created = (
select time_created -- Here it would still be recognized
from (
select * -- Here it won't anymore
...

How to get one common value from Database using UNION

2 records in above image are from Db, in above table Constraint are (SID and LINE_ITEM_ID),
SID and LINE_ITEM_ID both column are used to find a unique record.
My issues :
I am looking for a query it should fetch the recored from DB depending on conditions
if i search for PART_NUMBER = 'PAU43-IMB-P6'
1. it should fetch one record from DB if search for PART_NUMBER = 'PAU43-IMB-P6', no mater to which SID that item belong to if there is only one recored either under SID =1 or SID = 2.
2. it should fetch one record which is under SID = 2 only, from DB on search for PART_NUMBER = 'PAU43-IMB-P6', if there are 2 items one in SID=1 and other in SID=2.
i am looking for a query which will search for a given part_number depending on Both SID 1 and 2, and it should return value under SID =2 and it can return value under SID=1 only if the there are no records under SID=2 (query has to withstand a load of Million record search).
Thank you
Select *
from Table
where SID||LINE_ITEM_ID = (
select Max(SID)||Max(LINE_ITEM_ID)
from table
where PART_NUMBER = 'PAU43-IMB-P6'
);
If I understand correctly, for each considered LINE_ITEM_ID you want to return only the one with the largest value for SID. This is a common requirement and, as with most things in SQL, can be written in many different ways; the best performing will depend on many factors, not least of which is the SQL product you are using.
Here's one possible approach:
SELECT DISTINCT * -- use a column list
FROM YourTable AS T1
INNER JOIN (
SELECT T2.LINE_ITEM_ID,
MAX(T2.SID) AS max_SID
FROM YourTable AS T2
GROUP
BY T2.LINE_ITEM_ID
) AS DT1 (LINE_ITEM_ID, max_SID)
ON T1.LINE_ITEM_ID = DT1.LINE_ITEM_ID
AND T1.SID = DT1.max_SID;
That said, I don't recall seeing one that relies on the UNION relational operator. You could easily rewrite the above using the INTERSECT relational operator but it would be more verbose.
Well in my case it worked something like this:
select LINE_ITEM_ID,SID,price_1,part_number from (
(select LINE_ITEM_ID,SID,price_1,part_number from Table where SID = 2)
UNION
(select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 1 and line_item_id NOT IN (select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 2)))
This query solved my issue..........