Additional select if one select result is not null - sql

I am interested in the results found in table g, which shares a key, sample_name, with tables s and l. In this question the tables are
s - samples,
p - projects,
l - analyses, and
g, analysis g,
all within schema a.
In the interest of optimization, I only want to look for table g after having confirmed that l.analysis_g is NOT NULL.
Given: The only information that I start out with is the project names. The project table, p is linked with other tables by the samples table s. s is linked to every table. Table l contains types of analysis and each column is either NULL or 1.
In the example below I am trying a case but I realize this may be totally incorrect.
SELECT s.sample_name,
s.project_name,
g.*
FROM a.samples s
JOIN a.analyses l
ON s.sample_name = l.sample_name
JOIN a.analysis_g g
ON s.sample_name = g.sample_name
WHERE s.project_name IN (SELECT p.project_name
FROM a.projects p
WHERE p.project_name_other
IN ('PROJ_1',
'PROJ_2'))
;

Then perhaps in the where clause? It's still really hard to understand what you want . . .
SELECT s.sample_name,
s.project_name,
g.*
FROM a.samples s
JOIN a.analyses l
ON s.sample_name = l.sample_name
JOIN a.analysis_g g
ON s.sample_name = g.sample_name
WHERE s.project_name IN (SELECT p.project_name
FROM a.projects p
WHERE p.project_name_other
IN ('PROJ_1',
'PROJ_2'))
and l.analysis_g IS NOT NULL
;
As a side note, I think you could join p.project_name and avoid the where clause. AND I think you might want some inner joins -- but I'm not sure.
SELECT s.sample_name,
s.project_name,
g.*
FROM a.samples s
JOIN a.analyses l ON s.sample_name = l.sample_name
JOIN a.analysis_g g ON s.sample_name = g.sample_name
JOIN a.projects p ON s.project_name = p.project_name
WHERE p.project_name_other IN ('PROJ_1', 'PROJ_2')
and l.analysis_g IS NOT NULL

Again: Please show an example! We can't help if we have to guess, but I'll give it a try...
If l.analysis_g contains an ID from table g, then you can just use:
SELECT * FROM g
JOIN l on g.id = l.analysis_g
WHERE blah, blah, blah...
I removed your WHERE clause because you haven't provided enough information to allow anyone to help optimize it (if needed).

Related

CALCULATE PERCENT BY DEVIDING AGREGATED VALUE ON TOTAL

I'm trying to write a query that aggregates a column by a category and then find a percent of that category from total categories
WITH USERS_ENERGY AS
(SELECT D.REGION_ID,E.YEAR_DESC,HOME_TYPE_ID,OWNERSHIP_TYPE_ID,B.ELECTRICITY_TYPE_KEY,SUM(WEIGHT_FINAL) HH_BY_ELECTRICITY_TYPE
FROM
R_FACT_HOUSING_UNIT B
JOIN
RR_DIM_SAMPLE C ON B.SAMPLE_FORM_ID=C.SAMPLE_FORM_ID
JOIN
R_DIM_PLACES D ON C.FRAM_PLACE_ID=D.PLACE_ID
JOIN
R_DIM_YEAR E ON B.ROUND_YEAR=E.ID
JOIN
R_DIM_HOME_TYPE F ON F.HOME_TYPE_ID=B.HOME_TYPE_KEY
JOIN
R_DIM_OWNERSHIP_TYPE G ON G.OWNERSHIP_TYPE_ID=B.OWNERSHIP_TYPE_KEY
WHERE B.ELECTRICITY_TYPE_KEY IN(8200002,8200001)
GROUP BY D.REGION_ID,E.YEAR_DESC,HOME_TYPE_ID,OWNERSHIP_TYPE_ID,B.ELECTRICITY_TYPE_KEY),
ALL_HH AS
(
SELECT REGION_ID,YEAR_DESC,HOME_TYPE_ID,OWNERSHIP_TYPE_ID,SUM(B.WEIGHT_FINAL) TOTAL_HH
FROM
R_FACT_HOUSING_UNIT B
JOIN
RR_DIM_SAMPLE C ON B.SAMPLE_FORM_ID=C.SAMPLE_FORM_ID
JOIN
R_DIM_PLACES D ON C.FRAM_PLACE_ID=D.PLACE_ID
JOIN
R_DIM_YEAR E ON B.ROUND_YEAR=E.ID
JOIN
R_DIM_HOME_TYPE F ON F.HOME_TYPE_ID=B.HOME_TYPE_KEY
JOIN
R_DIM_OWNERSHIP_TYPE G ON G.OWNERSHIP_TYPE_ID=B.OWNERSHIP_TYPE_KEY
WHERE B.ELECTRICITY_TYPE_KEY IN(8200002,8200001)
GROUP BY REGION_ID,YEAR_DESC,HOME_TYPE_ID,OWNERSHIP_TYPE_ID
)
SELECT A."REGION_ID",A."YEAR_DESC",A."HOME_TYPE_ID",A."OWNERSHIP_TYPE_ID",A."ELECTRICITY_TYPE_KEY",A."HH_BY_ELECTRICITY_TYPE",TOTAL_HH FROM USERS_ENERGY A,ALL_HH B WHERE A.REGION_ID=B.REGION_ID AND A.YEAR_DESC=B.YEAR_DESC AND A.HOME_TYPE_ID=B.HOME_TYPE_ID AND A.OWNERSHIP_TYPE_ID=B.OWNERSHIP_TYPE_ID
that was the view I created.
when I tried to test it gave me wrong results
this was my test
SELECT ELECTRICITY_TYPE_KEY,SUM(HH_BY_ELECTRICITY_TYPE),SUM(TOTAL_HH)FROM MASDAR_HEN_3_A_A T
GROUP BY ELECTRICITY_TYPE_KEY
ORDER BY ELECTRICITY_TYPE_KEY
the result was:
but it supposes to be:
so if you devide values on total and add them it supposes to give 100%
Your query is almost impossible to follow. Some helpful advice for your query-writing:
Always use MEANINGFUL table alases, such as y for dim_year. Arbitrary letters are hard to follow.
Always use proper, explicit, standard JOIN syntax. Never use commas in the FROM clause.
As for your view, I think you just need analytic functions. A simpler version (assuming I haven't make mistakes on the table aliases):
SELECT p.REGION_ID, y.YEAR_DESC, ht.HOME_TYPE_ID, ot.OWNERSHIP_TYPE_ID, hu.ELECTRICITY_TYPE_KEY,
SUM(WEIGHT_FINAL) as HH_BY_ELECTRICITY_TYPE
SUM(SUM(WEIGHT_FINAL)) OVER (REGION_ID,YEAR_DESC, HOME_TYPE_ID, OWNERSHIP_TYPE_ID) as TOTAL_HH
FROM R_FACT_HOUSING_UNIT hu JOIN
RR_DIM_SAMPLE
ON hu.SAMPLE_FORM_ID = s.SAMPLE_FORM_ID JOIN
R_DIM_PLACES p
ON s.FRAM_PLACE_ID= p.PLACE_ID JOIN
R_DIM_YEAR y
ON hu.ROUND_YEAR = y.ID JOIN
R_DIM_HOME_TYPE ht
ON ht.HOME_TYPE_ID = hu.HOME_TYPE_KEY JOIN
R_DIM_OWNERSHIP_TYPE ot
ON ot.OWNERSHIP_TYPE_ID= hu.OWNERSHIP_TYPE_KEY
WHERE hu.ELECTRICITY_TYPE_KEY IN (8200002, 8200001)
GROUP BY p.REGION_ID, y.YEAR_DESC, ht.HOME_TYPE_ID, ot.OWNERSHIP_TYPE_ID, hu.ELECTRICITY_TYPE_KEY;
Oracle provides a RATIO_TO_REPORT analytic function to compute % of total for you.
SELECT
d.region_id,
e.year_desc,
home_type_id,
ownership_type_id,
b.electricity_type_key,
SUM(weight_final) hh_by_electricity_type,
100*RATIO_TO_REPORT(SUM(weight_final) OVER ( PARTITION BY REGION_ID,YEAR_DESC, HOME_TYPE_ID, OWNERSHIP_TYPE_ID ) pct_of_total
FROM
r_fact_housing_unit b
JOIN rr_dim_sample c ON b.sample_form_id = c.sample_form_id
JOIN r_dim_places d ON c.fram_place_id = d.place_id
JOIN r_dim_year e ON b.round_year = e.id
JOIN r_dim_home_type f ON f.home_type_id = b.home_type_key
JOIN r_dim_ownership_type g ON g.ownership_type_id = b.ownership_type_key
WHERE
b.electricity_type_key IN (
8200002,
8200001
)
GROUP BY
d.region_id,
e.year_desc,
home_type_id,
ownership_type_id,
b.electricity_type_key;
Here is another example, using the Oracle data dictionary for input data, for readers who do not have data model to test with:
SELECT owner,
sum(bytes) total_bytes,
100*ratio_to_report(sum(bytes)) over () pct_of_total
FROM dba_segments
GROUP BY owner;

Finding Non Entries within another data table (MS Access SQL)

I know there ust be a few hundred of this similar post, but I have tried all the other ways in MS Access and still cannot get it to work.
So my working code is as follows
SELECT FVR.*, V.[Week Commencing], F.Date, V.Date
FROM FVR
INNER JOIN (F
INNER JOIN V ON (F.[Week Commencing] = V.[Week Commencing]) AND (F.GUID = V.GUID))
ON (FVR.GUID = V.GUID) AND (FVR.GUID = F.GUID)
My desired effect would be to show the Dates of the "F" table that have no entries in the "V"Table.
Sorry for being crpytic on the tables but it is for work. I thoght i had a good idead on how to do most of this.
any help would be amazing as I have been pulling my hair over this for a while now.
Cheers and thanks in advance.
Editing this to add in the full code as it will make more sense.
I basically have am unable to produce the Data range from F(Forecast) that Does not match in V(Visits) am trying to bring up a list of forecasted dates that have not been visited using the Week Commencing and GUID from both tables, The FVR table is just a table that holds the regional data matching up to the GUID. #Hogan I tried your way and ended up with syntax errors, I almost got somewhere and then lost it again. I thought I had a bit more knowledge of SQL than this.
Full code is as follows
SELECT FVR.*, [Visits].[Week Commencing], [Forecast].[Forecast Date], [Visits].Date
FROM ForecastVisitRegion
INNER JOIN ([Forecast] INNER JOIN [Visits] ON ([Forecast].[Week Commencing] = [Visits].[Week Commencing])
AND ([Forecast].GUID = [Visits].GUID)) ON (FVR.GUID = [Visits].GUID)
AND (FVR.GUID = [External - Forecast].GUID)
Thanks again
Stephen Edwards
You need to use left joins:
SELECT FVR.*, V.[Week Commencing], NZ(V.Date,F.Date) as virtual_date
FROM FVR
LEFT JOIN F ON FVR.GUID = F.GUID
LEFT JOIN V ON FVR.GUID = V.GUID F.[Week Commencing] = V.[Week Commencing]
Not sure I understand why FVR is coming into the mix but you need a left Join.
Select F.*
from F
left join V on F.[Week Commencing] = V.[Week Commencing] AND F.GUID = V.GUID
where V.GUID is null
The left join ensures all the records (matched or not) from F are included in the result set. Then the where V.GUID is null removes the records where no match was found in V leaving you with the F records with no match.
Another approach would be to use the NOT EXISTS statement in the WHERE Clause
Select F.*
from F
where not exists (select * from V where F.[Week Commencing] = V.[Week Commencing] AND F.GUID = V.GUID)

SQL select results not appearing if a value is null

I am building a complex select statement, and when one of my values (pcf_auto_key) is null it will not disipaly any values for that header entry.
select c.company_name, h.prj_number, h.description, s.status_code, h.header_notes, h.cm_udf_001, h.cm_udf_002, h.cm_udf_008, l.classification_code
from project_header h, companies c, project_status s, project_classification l
where exists
(select company_name from companies where h.cmp_auto_key = c.cmp_auto_key)
and exists
(select status_code from project_status s where s.pjs_auto_key = h.pjs_auto_key)
and exists
(select classification_code from project_classification where h.pcf_auto_key = l.pcf_auto_key)
and pjm_auto_key = 11
--and pjt_auto_key = 10
and c.cmp_auto_key = h.cmp_auto_key
and h.pjs_auto_key = s.pjs_auto_key
and l.pcf_auto_key = h.pcf_auto_key
and s.status_type = 'O'
How does my select statement look? Is this an appropriate way of pulling info from other tables?
This is an oracle database, and I am using SQL Developer.
Assuming you want to show all the data that you can find but display the classification as blank when there is no match in that table, you can use a left outer join; which is much clearer with explicit join syntax:
select c.company_name, h.prj_number, h.description, s.status_code, h.header_notes,
h.cm_udf_001, h.cm_udf_002, h.cm_udf_008, l.classification_code
from project_header h
join companies c on c.cmp_auto_key = h.cmp_auto_key
join project_status s on s.pjs_auto_key = h.pjs_auto_key
left join project_classification l on l.pcf_auto_key = h.pcf_auto_key
where pjm_auto_key = 11
and s.status_type = 'O'
I've taken out the exists conditions as they just seem to be replicating the join conditions.
If you might not have matching data in any of the other tables you can make the other inner joins into outer joins in the same way, but be aware that if you outer join to project_status you will need to move the statatus_type check into the join condition as well, or Oracle will convert that back into an inner join.
Read more about the different kinds of joins.

Using "With" SQL on Oracle 10g causing errors

First ill tell you what the logic in my code is, after my last post it was pointed out to me that my procedure was inefficient and that i should think about logic of my approach..
To put it simply, i want to join a bunch of tables and filter them out to reflect a certain scheme, the process in "Z" in the bellow code
And then parse through that data using y on z...
Looking at the examples online i cant see why this code dosnt work, i have read in a few places that it may be a oracle 10g issue but note sure.. any recommendations would be great
The error i get is "ORA-00904: "Z"."COMMENTS": invalid identifier"
with
z as
(
Select *
FROM
(
iacd_note c
inner join iacd_ncr_note e on C.NOTE_ID=E.NOTE_ID
inner join iacd_ncr f on E.NCR_ID=F.NCR_ID
inner join iacd_ncr_iac g on F.NCR_ID=G.NCR_ID
)
WHERE c.create_date >= date'2014-01-01'
AND c.create_date < date'2014-12-31'
AND G.SCHEME_ID in (36,37,38,25,26,27,28,29,30,31,32,33,34,35,39,40,44,42,43,45, 48,49,50,51,52,55,56,57,58,68,69,70,71)
),
y as
(
Select *
From iacd_asset
)
SELECT y.bridge_no, COUNT(*) AS comment_cnt
FROM y INNER JOIN z
ON REGEXP_LIKE(z.comments, '(^|\W)BN' || y.bridge_no || '(\W|$)', 'i')
GROUP BY y.bridge_no
ORDER BY comment_cnt;
Z.COMMENTS should be part of the merges happening in z
This subquery is invalid SQL syntax:
Select *
FROM
(
iacd_note c
inner join iacd_ncr_note e on C.NOTE_ID=E.NOTE_ID
inner join iacd_ncr f on E.NCR_ID=F.NCR_ID
inner join iacd_ncr_iac g on F.NCR_ID=G.NCR_ID
)
WHERE ...
You can't put parentheses around the FROM clause. Instead:
Select *
FROM iacd_note c
inner join iacd_ncr_note e on C.NOTE_ID=E.NOTE_ID
inner join iacd_ncr f on E.NCR_ID=F.NCR_ID
inner join iacd_ncr_iac g on F.NCR_ID=G.NCR_ID
WHERE ...
Looks like the output of a with clause may not have the same column names as the original tables, so i selected all of z and noticed there was an odd automated name for the row i was after...

sql join history table to active table SSRS report

I'm trying to pull results from a database (sql server 2005) which takes 4 tables:
Subscriber S, Member M, ClaimLines L, ClaimHistoryLines H
Query is as follows:
select S.SBSB_ID, M.MEME_NAME,
(CASE L.CLCL_ID WHEN '' THEN H.CLCL_ID ELSE L.CLCL_ID END) AS CLAIM_ID
FROM CMC_CDDL_CL_LINE L, CMC_MEME_MEMBER M LEFT OUTER JOIN CMC_CLDH_DEN_HIST H
ON H.MEME_CK = M.MEME_CK, CMC_SBSB_SUBSC S
WHERE
S.SBSB_ID = '120943270' AND
L.MEME_CK = M.MEME_CK AND
M.SBSB_CK = S.SBSB_CK
This query successfully pulls in the result rows from the ClaimLines L table but no results from the History table are shown. I'm not sure how to do this, any sql experts out there that can help would be great. -Thanks!
CMC_CDDL_CL_LINE L, CMC_MEME_MEMBER M LEFT OUTER JOIN CMC_CLDH_DEN_HIST H
don't mix obsolete implied join syntax with left join. They don't play well together. Use the correct ANSII standard join syntax. Infact stop using the obsolete syntax altogether.
This was a very silly mistake on my part. I neglected to think of using a UNION which solved my problem and allowed me to pull from both places into a single results set without creating massive duplicate rows. Glad someone pointed out the proper way to write sql using ANSII standards.
select S.SBSB_ID, M.MEME_NAME,
L.CLCL_ID AS CLAIM_ID
FROM
CMC_SBSB_SUBSC S INNER JOIN CMC_MEME_MEMBER M ON S.SBSB_CK = M.SBSB_CK
INNER JOIN CMC_CDDL_CL_LINE L ON L.MEME_CK = M.MEME_CK
WHERE
S.SBSB_ID = '120943270'
UNION
select S.SBSB_ID, M.MEME_NAME,
H.CLCL_ID AS CLAIM_ID
FROM
CMC_SBSB_SUBSC S INNER JOIN CMC_MEME_MEMBER M ON S.SBSB_CK = M.SBSB_CK
INNER JOIN CMC_CLDH_DEN_HIST H ON H.MEME_CK = M.MEME_CK
WHERE
S.SBSB_ID = '120943270'