SQL Need advice how to add timestamp to this query - sql

I have this code:
select Users.phoneMac, Users.apMac, Locations.Lon, Locations.Lat
from Locations, Users
inner join (
select u.phoneMac, max(u.strenght) as most
from Users u, Locations l
where u.apMac = l.apMac
group by u.phoneMac
) as ij on ij.phoneMac=Users.phoneMac and Users.strenght = ij.most
where Locations.apMac = Users.apMac;
It worked for me fine but when I added more data to users table this query calculated results from all the data and I wanted to get results just from latest data. So I added timestamp to Users table.
So can you help me fix this code so it first take only data from latest timestamp for every user(users.phoneMac)(there can be more then 1 row of data for same phoneMac) and then do the rest of calculations.

You're already picking the max value of the "strenght" field and joining on that, so why not use the same approach again for your timestamp field? Something like:
SELECT Users.phoneMac, Users.apMac, Locations.Lon, Locations.Lat
FROM Locations
INNER JOIN Users
ON Users.apMac = Locations.apMac
INNER JOIN (
SELECT u.phoneMac, max(u.strenght) AS most
FROM Locations l
INNER JOIN Users u ON u.apMac = l.apMac
GROUP BY u.phoneMac) AS ij
ON ij.phoneMac = Users.phoneMac
AND Users.strenght = ij.most
INNER JOIN (
SELECT u2.phoneMac, max(u2.timestampfield) AS latest
FROM Locations l2
INNER JOIN Users u2 ON u2.apMac = l2.apMac
GROUP BY u2.phoneMac) AS ijk
ON ijk.phoneMac = Users.phoneMac
AND Users.timestampfield = ij.latest;
(By the way, using the old join syntax with comma and the WHERE clause makes it harder to understand the logic, and occasionally makes the logic wrong. The new join syntax with ON is really a lot better.)

Related

How to not pull in duplicate rows when joining tables in Vertica SQL

Is it possible to not pull in duplicate rows when creating a table from multiple table joins in Vertica SQL? I am wanting to filter out entire duplicate rows - so rows where all column values in that row are the same as another row.
I tried doing this using Group By after searching online, but I still find a large amount of duplicate rows. FYI I am checking for duplicates by downloading my data, opening with excel, and removing duplicates. My end goal is to not have to download the data because we are using a system where we do not have a method for re-loading the data onto the server system we are using (#ThanksCerner).
I was reading a few methods where you create a temporary table and delete duplicates, but also read that it is not recommended to use DELETE for tables with a large # of records, so I was trying to avoid that.
Thanks in advance!
Update: This is the query I am using. I will work on creating some test data I can share for it
SELECT DISTINCT c.condition_code, c.condition_primary_display,
c.effective_date_id AS condition_effective_date,
bc.member_id, bc.plan_name, bc.payer_name,
e.facility, e.service_delivery_location, e.hospital_service_display,
e.encounter_type_display, e.encounter_type_primary_display,
e.discharge_disposition_display, e.admission_source_display,
e.status_display, e.actual_arrival_dt_tm, e.discharge_dt_tm,
p.full_name AS patient_name, p.postal_cd, p.county_display,
p.state_primary_display,
pd.birth_date, pd.ethnicity_primary_display, pd.gender_primary_display,
pr.race_display,
po.name AS provider_name, po.provider_id,
epr.relationship_type_primary_display
FROM PH_D_Person p
LEFT OUTER JOIN PH_D_Person_Demographics pd
ON p.empi_id = pd.empi_id AND p.population_id = pd.population_id
LEFT OUTER JOIN PH_D_Person_Race pr
ON pd.empi_id = pr.empi_id AND pd.population_id = pr.population_id
LEFT OUTER JOIN PH_F_Condition c
ON pr.empi_id = c.empi_id AND pr.population_id = c.population_id
LEFT OUTER JOIN PH_F_Encounter e
ON c.encounter_id = e.encounter_id AND c.empi_id = e.empi_id AND
c.population_id = e.population_id
LEFT OUTER JOIN PH_F_Encounter_Benefit_Coverage bc
ON e.encounter_id = bc.encounter_id AND e.empi_id = bc.empi_id AND
e.population_id = bc.population_id
LEFT OUTER JOIN PH_F_Encounter_Personnel_Reltn epr
ON bc.encounter_id = epr.encounter_id AND bc.empi_id = epr.empi_id AND
bc.population_id = epr.population_id
LEFT OUTER JOIN PH_D_Provider po
ON epr.provider_id = po.provider_id
WHERE c.condition_code IN ('J44.0', 'J44.1', 'J44.9', 'J47.1', 'J47.0',
'J47.9', 'J43.2', 'J43.9', 'J41.8', 'J41.1', 'J43.8', 'J43.1', 'J41.0',
'J43.0', 'J42')
AND year(e.actual_arrival_dt_tm) ='2017'
AND year(e.discharge_dt_tm) ='2017'
ORDER BY bc.member_id DESC;

MS Access INNER JOIN/LEFT JOIN problems

I have the following SQL string which tries to combine an INNER JOIN with a LEFT JOIN in the FROM section.
As you can see I use table VIP_APP_VIP_SCENARIO_DETAIL_LE to perform the query. When I use it against this table, Access give me an "Invalid Operation" error.
Interestingly, when I use the EXACT same query using the VIP_APP_VIP_SCENARIO_DETAIL_BUDGET or VIP_APP_VIP_SCENARIO_DETAIL_ACTUALS table, it performs flawlessly.
So why would it work on two tables but not the other? All fields are in all tables and the data types are correct.
As a side note: on the query with the error, if I change the LEFT JOIN to an INNER JOIN, it runs with no problem! I really need a LEFT JOIN though.
SELECT
D.MATERIAL_NUMBER,
D.MATERIAL_DESCRIPTION,
D.PRODUCTION_LOT_SIZE,
D.STANDARDS_NAME,
D.WORK_CENTER,
S.OP_SHORT_TEXT,
S.OPERATION_CODE,
D.LINE_SPEED_UPM,
D.PERCENT_STD,
D.EQUIPMENT_SU,
D.EQUIPMENT_CU,
D.OPERATOR_NUM,
V.COSTING_LOT_SIZE,
V.VOL_TOTAL_ADJ
FROM
([STDS_SCENARIO: TEST] AS D INNER JOIN MASTER_SUMMARY AS S ON
D.MATERIAL_NUMBER = S.MATERIAL_NUMBER AND D.WORK_CENTER = S.WORK_CENTER)
LEFT JOIN
(SELECT ITEM_CODE, COSTING_LOT_SIZE, VOL_TOTAL_ADJ
FROM
VIP_APP_VIP_SCENARIO_DETAIL_LE
WHERE SCENARIO_ID = 16968) AS V ON D.MATERIAL_NUMBER = V.ITEM_CODE
ORDER BY D.MATERIAL_NUMBER, D.STANDARDS_NAME, S.OPERATION_CODE;
tried to mock this up in SQL server with some tables of my own, but the structure seemed to work, this follows the pattern referenced above. (hopefully no syntax errors left here)
SELECT * FROM (
select
D.MATERIAL_NUMBER,
D.MATERIAL_DESCRIPTION,
D.PRODUCTION_LOT_SIZE,
D.STANDARDS_NAME,
D.WORK_CENTER,
S.OP_SHORT_TEXT,
S.OPERATION_CODE,
D.LINE_SPEED_UPM,
D.PERCENT_STD,
D.EQUIPMENT_SU,
D.EQUIPMENT_CU,
D.OPERATOR_NUM
FROM [STDS_SCENARIO: TEST] D
INNER JOIN MASTER_SUMMARY S
ON D.MATERIAL_NUMBER = S.MATERIAL_NUMBER AND D.WORK_CENTER = S.WORK_CENTER) AS J
LEFT JOIN
(SELECT ITEM_CODE, COSTING_LOT_SIZE, VOL_TOTAL_ADJ
FROM
VIP_APP_VIP_SCENARIO_DETAIL_LE
WHERE SCENARIO_ID = 16968) AS V ON J.MATERIAL_NUMBER = V.ITEM_CODE
ORDER BY J.MATERIAL_NUMBER, J.STANDARDS_NAME, J.OPERATION_CODE;
Had help from a friend and we discovered that it was a casting problem between a linked Oracle table and the Access table. To fix the problem we casted both sides of the linked fields to a string:
CSTR(D.[MATERIAL_NUMBER]) = CSTR(V.[ITEM_CODE])

Changing old join to new join

I am new to SQL so any help is greatly appreciated. I have a query that seems to be working that has old style joins, and I need to change it to new style joins. the current query is like:
SELECT
STAR.V_DISASTER_DIMENSIONS .DISASTER_NUMBER,
STAR.PA_PROJECT_DIMENSIONS .PW_NUMBER,
STAR.PA_PROJECT_SITE_DIMENSIONS.SITE_NUMBER,
STAR.PA_PROJECT_FACTS .PROJECT_AMOUNT,
STAR.PA_MITIGATION_DIMENSIONS .MITIGATION_ACTIVITY_STATUS
FROM
STAR.V_DISASTER_DIMENSIONS,
STAR.PA_PROJECT_DIMENSIONS,
STAR.PA_PROJECT_SITE_DIMENSIONS,
STAR.PA_MITIGATION_DIMENSIONS,
STAR.PA_PROJECT_FACTS,
STAR.PA_PROJECT_SITE_FACTS
WHERE
( STAR.PA_PROJECT_DIMENSIONS.PA_PROJECT_ID = STAR.PA_PROJECT_FACTS.PA_PROJECT_ID )
AND
( STAR.PA_PROJECT_FACTS.DISASTER_ID = STAR.V_DISASTER_DIMENSIONS.DISASTER_ID )
AND
( STAR.PA_MITIGATION_DIMENSIONS.PA_MITIGATION_ID = STAR.PA_PROJECT_FACTS.PA_PROJECT_ID )
AND
( STAR.PA_PROJECT_SITE_FACTS.PA_PROJECT_ID = STAR.PA_MITIGATION_DIMENSIONS.PA_MITIGATION_ID )
AND
( STAR.PA_PROJECT_SITE_FACTS.DISASTER_ID = STAR.V_DISASTER_DIMENSIONS.DISASTER_ID )
AND
( STAR.PA_PROJECT_SITE_FACTS.PA_PROJECT_ID = STAR.PA_PROJECT_DIMENSIONS.PA_PROJECT_ID )
AND
( STAR.PA_PROJECT_SITE_FACTS.PA_PROJECT_SITE_ID = STAR.PA_PROJECT_SITE_DIMENSIONS.PA_PROJECT_SITE_ID )
My attempt to convert is below. I don't know where to put the extra conditions because they are not 1 to 1 with tables.
FROM
STAR.V_DISASTER_DIMENSIONS
JOIN STAR.PA_PROJECT_SITE_FACTS ON STAR.PA_PROJECT_SITE_FACTS.DISASTER_ID = STAR.V_DISASTER_DIMENSIONS.DISASTER_ID
JOIN STAR.PA_PROJECT_DIMENSIONS ON STAR.PA_PROJECT_SITE_FACTS.PA_PROJECT_ID = STAR.PA_PROJECT_DIMENSIONS.PA_PROJECT_ID
JOIN STAR.PA_PROJECT_SITE_DIMENSIONS ON STAR.PA_PROJECT_SITE_FACTS.PA_PROJECT_SITE_ID = STAR.PA_PROJECT_SITE_DIMENSIONS.PA_PROJECT_SITE_ID
JOIN STAR.PA_MITIGATION_DIMENSIONS ON STAR.PA_PROJECT_SITE_FACTS.PA_PROJECT_ID = STAR.PA_MITIGATION_DIMENSIONS.PA_MITIGATION_ID
JOIN STAR.PA_PROJECT_FACTS ON (
STAR.PA_PROJECT_FACTS .DISASTER_ID = STAR.V_DISASTER_DIMENSIONS.DISASTER_ID AND
STAR.PA_MITIGATION_DIMENSIONS.PA_MITIGATION_ID = STAR.PA_PROJECT_FACTS .PA_PROJECT_ID AND
STAR.PA_PROJECT_DIMENSIONS .PA_PROJECT_ID = STAR.PA_PROJECT_FACTS .PA_PROJECT_ID
)
Change , to INNER JOINs with ON condition:
SELECT
STAR.V_DISASTER_DIMENSIONS.DISASTER_NUMBER,
STAR.PA_PROJECT_DIMENSIONS.PW_NUMBER,
STAR.PA_PROJECT_SITE_DIMENSIONS.SITE_NUMBER,
STAR.PA_PROJECT_FACTS.PROJECT_AMOUNT,
STAR.PA_MITIGATION_DIMENSIONS.MITIGATION_ACTIVITY_STATUS
FROM
STAR.PA_PROJECT_DIMENSIONS PD
INNER JOIN STAR.PA_PROJECT_FACTS PF ON PD.PA_PROJECT_ID=PF.PA_PROJECT_ID
INNER JOIN STAR.V_DISASTER_DIMENSIONS DD ON DD.DISASTER_ID=PF.DISASTER_ID
INNER JOIN STAR.PA_MITIGATION_DIMENSIONS MD ON MD.PA_MITIGATION_ID=PF.PA_PROJECT_ID
INNER JOIN STAR.PA_PROJECT_SITE_FACTS PSF ON PSF.PA_PROJECT_ID=MD.PA_MITIGATION_ID
AND PSF.DISASTER_ID=DD.DISASTER_ID
AND PSF.PA_PROJECT_ID=PD.PA_PROJECT_ID
INNER JOIN STAR.PA_PROJECT_SITE_DIMENSIONS PSD ON PSD.PA_PROJECT_SITE_ID=PSF.PA_PROJECT_SITE_ID
Select * from
a,b
where a.z = b.y
would be written as
Select * from
a
INNER JOIN
b
ON a.z = b.y
It is easy. Just start with the facts table and join related tables on foreign key = key.
First of all you should use table aliases to get the query more readable. Also use some lowercase letters, too.
Then just write the table names (or the aliases) on paper and draw a line for each condition from one table to the other. Then pick one table to start with, e.g. pa_project_site_dimensions which is only linked to one table.
SELECT
dd.disaster_number,
pd.pw_number,
psd.site_number,
psf.project_amount,
md.mitigation_activity_status
FROM star.pa_project_site_dimensions psd
JOIN star.pa_project_site_facts psf ON psf.pa_project_site_id = psd.pa_project_site_id
JOIN star.v_disaster_dimensions dd ON dd.disaster_id = psf.disaster_id
JOIN star.pa_mitigation_dimensions md ON md.pa_mitigation_id = psf.pa_project_id
JOIN star.pa_project_dimensions pd ON pd.pa_project_id = psf.pa_project_id
JOIN star.pa_project_facts pf ON pf.disaster_id = dd.disaster_id
AND pf.pa_project_id = md.pa_mitigation_id
AND pf.pa_project_id = pd.pa_project_id
;
However, this is a strange query. First of all there is no limiting condition, you simply join all records, rather than retrieving data for, say, one particular project.
Moreover, you deal with several dimensions. Obviously a project has facts (pa_project_facts) and dimensions (pa_project_dimensions). With 5 facts and 3 dimensions you'd get 15 rows with all their combinations. Then there are also project sites it seems (maybe a table pa_project_sites we don't see in the query). Either that project site has facts on its own (pa_project_site_facts) that you also combine with all rows, or a project site is linked to a project fact via pa_project_site_facts, but then pa_project_facts wouldn't have to be joined by pa_project_id only, but also by some fact ID.
Also this looks strange: md.pa_mitigation_id = psf.pa_project_id. Is a mitigation the same as a project?
So after all have a look at all columns that need to be joined on. Think about how the tables are related and if you are not building combinations that make no sense.

How can I do a SQL join to get a value 4 tables farther from the value provided?

My title is probably not very clear, so I made a little schema to explain what I'm trying to achieve. The xxxx_uid labels are foreign keys linking two tables.
Goal: Retrieve a column from the grids table by giving a proj_uid value.
I'm not very good with SQL joins and I don't know how to build a single query that will achieve that.
Actually, I'm doing 3 queries to perform the operation:
1) This gives me a res_uid to work with:
select res_uid from results where results.proj_uid = VALUE order by res_uid asc limit 1"
2) This gives me a rec_uid to work with:
select rec_uid from receptor_results
inner join results on results.res_uid = receptor_results.res_uid
where receptor_results.res_uid = res_uid_VALUE order by rec_uid asc limit 1
3) Get the grid column I want from the grids table:
select grid_name from grids
inner join receptors on receptors.grid_uid = grids.grid_uid
where receptors.rec_uid = rec_uid_VALUE;
Is it possible to perform a single SQL that will give me the same results the 3 I'm actually doing ?
You're not limited to one JOIN in a query:
select grids.grid_name
from grids
inner join receptors
on receptors.grid_uid = grids.grid_uid
inner join receptor_results
on receptor_results.rec_uid = receptors.rec_uid
inner join results
on results.res_uid = receptor_results.res_uid
where results.proj_uid = VALUE;
select g.grid_name
from results r
join resceptor_results rr on r.res_uid = rr.res_uid
join receptors rec on rec.rec_uid = rr.rec_uid
join grids g on g.grid_uid = rec.grid_uid
where r.proj_uid = VALUE
a small note about names, typically in sql the table is named for a single item not the group. thus "result" not "results" and "receptor" not "receptors" etc. As you work with sql this will make sense and names like you have will seem strange. Also, one less character to type!

ms access query - Filter out values from another query

I've got a query running that pulls out the records I need.
I want to run another query that pulls out all the other records (excluding the ones in the first query).
I've read up on NOT IN and NOT LIKE but can't seem to get them to work.
The first query is named: qryHunnersPatients
Here's the code for the second query that I have so far:
Right now this is just pulling all the records - but I want to exclude those records in the qryHunnersPatients query
SELECT
tblPatientHistoryBaseline.ID,
tblPatientHistoryBaseline.Age,
[tblPatientHistoryBaseline].[Age]-[tblPatientHistoryBaseline].[UrinarySxBegan] AS Duration,
tblPatientHistoryBaseline.IBS,
tblQuestionnaires.UPOINTTotal,
tblQuestionnaires.U,
tblQuestionnaires.P,
tblQuestionnaires.O,
tblQuestionnaires.I,
tblQuestionnaires.N,
tblQuestionnaires.T,
tblQuestionnaires.ICSITotal,
tblQuestionnaires.ICPITotal
FROM
tblPatientHistoryBaseline
INNER JOIN
tblQuestionnaires
ON
(tblPatientHistoryBaseline.Visit = tblQuestionnaires.Visit)
AND
(tblPatientHistoryBaseline.ID = tblQuestionnaires.ID);
UPDATE:
I just tried the WHERE NOT EXISTS using the code below:
SELECT
tblPatientHistoryBaseline.ID,
tblPatientHistoryBaseline.Age,
[tblPatientHistoryBaseline].[Age]-[tblPatientHistoryBaseline].[UrinarySxBegan] AS Duration,
tblPatientHistoryBaseline.IBS,
tblQuestionnaires.UPOINTTotal,
tblQuestionnaires.U,
tblQuestionnaires.P,
tblQuestionnaires.O,
tblQuestionnaires.I,
tblQuestionnaires.N,
tblQuestionnaires.T,
tblQuestionnaires.ICSITotal,
tblQuestionnaires.ICPITotal
FROM
tblPatientHistoryBaseline
INNER JOIN
tblQuestionnaires
ON
(tblPatientHistoryBaseline.Visit = tblQuestionnaires.Visit)
AND
(tblPatientHistoryBaseline.ID = tblQuestionnaires.ID)
WHERE NOT EXISTS
(SELECT ID
FROM qryHunnersPatients AS hunners
WHERE hunners.ID = tblPatientHistoryBaseline.ID);
You need a SubQuery. As In understand that your Query qryHunnersPatients gives you the list of records that you do not wish to see, you need to include that in the NOT IN part of the Query.
SELECT
tblPatientHistoryBaseline.ID,
tblPatientHistoryBaseline.Age,
[tblPatientHistoryBaseline].[Age]-[tblPatientHistoryBaseline].[UrinarySxBegan] AS Duration,
tblPatientHistoryBaseline.IBS,
tblQuestionnaires.UPOINTTotal,
tblQuestionnaires.U,
tblQuestionnaires.P,
tblQuestionnaires.O,
tblQuestionnaires.I,
tblQuestionnaires.N,
tblQuestionnaires.T,
tblQuestionnaires.ICSITotal,
tblQuestionnaires.ICPITotal
FROM
tblPatientHistoryBaseline
INNER JOIN
tblQuestionnaires
ON
(tblPatientHistoryBaseline.Visit = tblQuestionnaires.Visit)
AND
(tblPatientHistoryBaseline.ID = tblQuestionnaires.ID)
WHERE
tblPatientHistoryBaseline.ID
NOT IN
(SELECT qryHunnersPatients.ID FROM qryHunnersPatients);
Assuming ID is unique, you can use WHERE NOT EXISTS:
SELECT {FieldList}
FROM tblPatientHistoryBaseline AS baseline
INNER JOIN tblQuestionnaires AS quest
ON (baseline.Visit = quest.Visit)
AND (baseline.ID = quest.ID);
WHERE NOT EXISTS (
SELECT ID
FROM qryHunnersPatients AS hunners
WHERE hunners.ID = baseline.ID
)
You don't need to bother using the aliases I've added to; I've just added them for readability.