Oracle Subquery - How to? - sql

I have 2 tables that look like:
GL_ROLLUP
Responsibility Responsibility_L3
15500 15B
15445 15C
15515 15B
15494 15C
15600 15D
GL_Detail
Responsibility Expense Amount
15500 6501 30.51
15445 6508 75.60
15515 6535 45.68
15494 6508 65.50
15600 6505 84.39
My query right now is pulling the data from the GL_Detail table; however what I want to be able to due is use the search parameter Responsibility_L3 found in GL_ROLLUP so I can query all Responsibilities within this rolled up value (instead of doing a range or a " = '15500' or....."). I tried doing this a few times, but my query seems to get stuck and never brings data back.
Any help would be greatly appreciated!

SELECT d.Responsibility, r.Responsibility_L3, d.Expense, d.Amount
FROM GL_Detail d LEFT JOIN GL_ROLLUP r ON r.Responsibility = d.Responsibility
ORDER BY Responsibility_L3
Does that get you what you are looking for?

The required query is a simple one:
select d.responsibility
, d.expense
, d.amount
from GL_ROLLUP r
inner join GL_Detail d
on d.responsibility = r.responsibility
where r.responsibility_l3 = :l3_search_param -- use appropriate notation
"my query seems to get stuck and never brings data back"
If the above query suffers the same fate, that's a performance issue. You will need to post an explain plan, details of data volumes,indexes, etc

Related

Add Math function to SQL Query

New to SQL and I am trying to run a query that pulls all our item codes, lot number, and qty on hand.
Each lot number has multiple entries due to adjustments. I need a way of running my query and having it add or subtract to get the actual qty on hand for each lot and only show me lots that are in the negatives. I have tried playing with SSRS but I cant get it right. I'm using SQL 2008R2.
SELECT
IMLAYER.ITEM_CODE
,IMMSTR.ITEM_DESC
,IMLAYER.LOT_NO
,IMLAYER.QTY_ON_HAND
FROM
IMLAYER
INNER JOIN
IMMSTR
ON
IMLAYER.ITEM_CODE = IMMSTR.ITEM_CODE
WHERE
(IMLAYER.QTY_ON_HAND < 0);
I believe I understand the requirements correctly, but if not please comment and I can update the query:
SELECT
M.ITEM_CODE
,M.ITEM_DESC
,L.LOT_NO
,'SUM_OF_QTY_ON_HAND' = SUM(L.QTY_ON_HAND)
FROM
IMLAYER L
INNER JOIN
IMMSTR M
ON L.ITEM_CODE = M.ITEM_CODE
GROUP BY
M.ITEM_CODE
,M.ITEM_DESC
,L.LOT_NO
HAVING
SUM(L.QTY_ON_HAND) < 0
HAVING is the trick you are looking for to be able to use an aggregate function for filtering.

Defaulting missing data

I have a complex set of schema that I am trying to pull data out of for a report. The query for it joins a bunch of tables together and I am specifically looking to pull a subset of data where everything for it might be null. The original relations for the tables look as such.
Location.DeptFK
Dept.PK
Section.DeptFK
Subsection.SectionFK
Question.SubsectionFK
Answer.QuestionFK, SubmissionFK
Submission.PK, LocationFK
From here my problems begin to compound a little.
SELECT Section.StepNumber + '-' + Question.QuestionNumber AS QuestionNumberVar,
Question.Question,
Subsection.Name AS Subsection,
Section.Name AS Section,
SUM(CASE WHEN (Answer.Answer = 0) THEN 1 ELSE 0 END) AS NA,
SUM(CASE WHEN (Answer.Answer = 1) THEN 1 ELSE 0 END) AS AnsNo,
SUM(CASE WHEN (Answer.Answer = 2) THEN 1 ELSE 0 END) AS AnsYes,
(select count(distinct Location.Abbreviation) from Department inner join Plant on location.DepartmentFK = Department.PK WHERE(Department.Name = 'insertParameter'))
as total
FROM Department inner join
section on Department.PK = section.DepartmentFK inner JOIN
subsection on Subsection.SectionFK = Section.PK INNER JOIN
question on Question.SubsectionFK = Subsection.PK INNER JOIN
Answer on Answer.QuestionFK = question.PK inner JOIN
Submission on Submission.PK = Answer.SubmissionFK inner join
Location on Location.DepartmentFK = Department.PK AND Location.pk = Submission.PlantFK
WHERE (Department.Name = 'InsertParameter') AND (Submission.MonthTested = '1/1/2017')
GROUP BY Question.Question, QuestionNumberVar, Subsection.Name, Section.Name, Section.StepNumber
ORDER BY QuestionNumberVar;
There are 15 total locations, with this query I get 12. If I remove a relation in the join for Location I get 15 total locations but my answer data gets multiplied by 15. My issue is that not all locations are required to test at the same time so their answers should default to NA, They don't get records placed in the DB so the relationship between Location/Submission is absent.
I have a workaround almost in place via the select count distinct but, The second part is a query for finding what each location answered instead of a sum which brings the problem right back around. It also has to be dynamic because the input parameters for a department won't bring a static number of locations back each time.
I am still learning my SQL so any additional material to look at for building this query would also be appreciated. So I guess the big question here is, How would I go about creating default data in this query for anytime the Location/Submission relation has a null value?
Edit: Dummy Data
QuestionNumberVar | Section | Subsection | Question | AnsYes | AnsNo | NA (expected)
1-1.1 Math Algebra Did you do your homework? 10 1 1(4)
1-1.2 Math Algebra Did your dog eat it? 9 3 0(3)
2-1.1 English Greek Did you do your homework? 8 0 4(7)
I have tried making left joins at various applicable portions of the code to no avail. All attempts at left joins have ended with no effect on info output. This query feeds into the Dataset for an SSRS report. There are a couple workarounds for this particular section via an expression to take total Locations and subtract AnsYes and AnsNo to get the true NA value but as explained above doesn't help with my next query.
Edit: SQL Server 2012 for those who asked
Edit: my attempt at an isnull() on the missing data returns nothing I suspect because the query already eliminates the "null/missing" data. Left joining while doing this has also failed. The point of failure is on Submissions. if we bind it to Locations there are locations missing but if we don't bind it there are multiplied duplicates because Department has a One-To-Many with Location and not vice versa. I am unable to make any schema changes to improve this process.
There is a previous report that I am trying to emulate/update. It used C# logic to process data and run multiple queries to attain the same data. I don't have this luxury. (previous report exports to excel directly instead of SSRS). Here is the previous logic used.
select PK from Department where Name = 'InsertParameter';
select PK from Submission where LocationFK = 'Location.PK_var' and MonthTested = '1/1/2017'
Then it runs those into a loop where it processes nulls into NA using C# logic
EDIT (Mediocre Solution): I ended up doing the workaround of making a calculated field that subtracts Yes and No from the total # of Locations that have that Dept. This is a mediocre solution because I didn't solve my original problem and made 3 datasets that should have been displayed as a singular dataset. One for question info, one for each locations answer and one for locations that didnt participate. If a true answer comes up I will check its validity but for now, Problem psuedo solved.

Query does execute without errors, but returns no output

My query here has a sub-query in it but it returns no output, but in reality it has to give some output because I manually checked and output exists.I have posted the query below.
select mac.mac_id,mac.mac1,mac.mac_type,record.soc_id
from mso_charter.mac
join record on mac.record_id = record.record_id
where mac.mac_type='ethB' and record.soc_id IN (select soc from d);
Sample data is below
mac_id mac1 mac_type record_id--- for table mac
1 6142 ethA 1
2 6412 ethB 1
3 2313 ethC 1
record_id soc_id ---- for table record
1 Qu132
1 as432
1 342aq
soc --- for table d
a12w2
23we
qw12
mso_charter is the schema name mac,d and record is the table name.
Note that your subquery is actually still a join and can be written that way:
select mac.mac_id,mac.mac1,mac.mac_type,record.soc_id
from mso_charter.mac
join record using(record_id)
join d on record.soc_id = d.soc
where mac.mac_type='ethB';
As per the comment we still need a data set to reproduce and help.
Should be select soc_id from d instead of select select soc from d
According to your sample data, d has a column soc_id. That should be used for the comparison:
select m.mac_id, m.mac1, m.mac_type, r.soc_id
from mso_charter.mac m join
record r
on m.record_id = r.record_id
where m.mac_type = 'ethB' and
r.soc_id in (select d.soc_id from d);
It is possible that ids look the same but are not, because of international characters, hidden characters, spaces in the wrong place, and so on.
If this doesn't work then try the following:
Remove the soc_id condition and see if any rows match the first condition and join.
If that still returns nothing, remove the entire where clause to see if anything matches the join.
None of your record.soc_id match any of your d.soc_id. So you get no row.
Also, you write select soc from d. soc, not soc_id. Typo or error?
So, thanks to all who tried helping me in this situation. I actually had did a very silly mistake.The reason I am posting the right answer is probably because if someone else in future get stuck in such a issue or something similar it would be helpful to them.
select m.mac_id,m.mac,m.mac_type,r.soc_id
from mso_charter.mac m
join mso_charter.record r on m.record_id = r.record_id
where m.mac_type = 'ethB' and r.soc_id IN (select d.soc_id from d);
Mistake was I had not mentioned the schema name while performing join and there were multiple tables named record in other schema's, it was just out of frustration we tend to forget small things which costed me few hours to work over.

Produce a Query viewing multiple tables

I have been given a database, the structure and data values are all unchangable and have been provided with a question.
Produce a query to list the holiday code, holiday description, holiday duration and site description for all holidays which visit site code 101. Your answer must not assume that site code 101 will always have the same site description.
I am confused on how to tackle this question. I have tried Multiple joins, different dot notation and googled the question to hell and back. Any help?
Table 1 - Holiday_Details
Holiday_Code - Country_Visited - Holiday_Duration - Holiday_Desc - Rating_Code - Cost
Table 2 - Site_Of_Holiday
Site_Description - Site_Code
Table 3 - Site_Visited
Holiday_Code - Site_Code
Comments have asked for previous attempts. This was my first.
SELECT holiday_code,
holiday_desc,
holiday_duration site_of_holiday.Site_Name
FROM holiday_details
JOIN site_visited
ON holiday_code = site_visited.holiday_code
JOIN site_of_holiday
ON site_visited.site_code = site_of_holiday.site_code
WHERE site_of_holiday.site_code = 101;
For future reference, you'll get a better response if you post a lot more detail about your failed attempts. By that, I mean code. Using SO to solve your homework assignments is frowned upon but, like a commenter said, once you've wracked your brain we're willing to help.
You seem like you may have actually tried real hard, so I'll throw you a bone...
The trick to navigating multiple tables is to find the "pairs" of matching columns. In this case you want to find a path between the tables Site_Of_Holiday (which has Site_Description) and Holiday_Details (which has everything else).
The columns that match between each pair of tables are:
Holiday_Code is found in both Site_Visited and Holiday_Details
Site_Code is found in both Site_Of_Holiday and Site_Visited
This allows you to build a path between the tables that contain all of the columns we want in the output. You would do this, in this case, using INNER JOINs across those matching column pairs.
Once you've joined the tables, think of the result like a giant table whose columns include all columns from all three tables (prefixed with whatever you 'name' the table during the joins). Now you just filter on the Site_Code with the usual WHERE clause.
Here's the full example - let me know if it works for you:
SELECT hd.Holiday_Code, hd.Holiday_Desc, hd.Holiday_Duration, soh.Site_Description
FROM Holiday_Details hd
INNER JOIN Site_Visited sv ON hd.Holiday_Code = sv.Holiday_Code
INNER JOIN Site_Of_Holiday soh ON sv.Site_Code = soh.Site_Code
WHERE sv.Site_Code = 101
Good luck!
P.S. In case any Americans get a similar assignment, here's the translation ;-)
SELECT vd.Vacation_Code, vd.Vacation_Desc, vd.Vacation_Duration, sov.Site_Description
FROM Vacation_Details vd
INNER JOIN Site_Visited sv ON vd.Vacation_Code = sv.Vacation_Code
INNER JOIN Site_Of_Vacation sov ON sv.Site_Code = sov.Site_Code
WHERE sv.Site_Code = 101

SUM(a*b) not working

I have a PHP page running in postgres. I have 3 tables - workorders, wo_parts and part2vendor. I am trying to multiply 2 table column row datas together, ie wo_parts has a field called qty and part2vendor has a field called cost. These 2 are joined by wo_parts.pn and part2vendor.pn. I have created a query like this:
$scoreCostQuery = "SELECT SUM(part2vendor.cost*wo_parts.qty) as total_score
FROM part2vendor
INNER JOIN wo_parts
ON (wo_parts.pn=part2vendor.pn)
WHERE workorder=$workorder";
But if I add the costs of the parts multiplied by the qauntities supplied, it adds to a different number than what the script is doing. Help....I am new to this but if someone can show me in SQL I can modify it for postgres. Thanks
Without seeing example data, there's no way for us to know why you're query totals are coming out differently that when you do the math by hand. It could be a bad join, so you are getting more/less records than you expected. It's also possible that your calculations are off. Pick an example with the smallest number of associated records & compare.
My suggestion is to add a GROUP BY to the query:
SELECT SUM(p.cost * wp.qty) as total_score
FROM part2vendor p
JOIN wo_parts wp ON wp.pn = p.pn
WHERE workorder = $workorder
GROUP BY workorder
FYI: MySQL was designed to allow flexibility in the GROUP BY, while no other db I've used does - it's a source of numerous questions on SO "why does this work in MySQL when it doesn't work on db x...".
To Check that your Quantities are correct:
SELECT wp.qty,
p.cost
FROM WO_PARTS wp
JOIN PART2VENDOR p ON p.pn = wp.pn
WHERE p.workorder = $workorder
Check that the numbers are correct for a given order.
You could try a sub-query instead.
(Note, I don't have a Postgres installation to test this on so consider this more like pseudo code than a working example... It does work in MySQL tho)
SELECT
SUM(p.`score`) AS 'total_score'
FROM part2vendor AS p2v
INNER JOIN (
SELECT pn, cost * qty AS `score`
FROM wo_parts
) AS p
ON p.pn = p2v.pn
WHERE p2n.workorder=$workorder"
In the question, you say the cost column is in part2vendor, but in the query you reference wo_parts.cost. If the wo_parts table has its own cost column, that's the source of the problem.