Access SQL query that uses a field from one table within where clause to create a calculated field - sql

This really isn't that complicated but I can't wrap my head around it. Ive searched thoroughly but even coming up with a search string or title for this question was hard enough. The explanation will tell all:
Table "labelDrops" has fields "PO" and "Qty" (among other unrelated fields)
Table "imageLiveCount" has field "PO"
I want to count instances (count(imageLiveCount.id)) where imageLiveCoount.PO = labelDrops.PO and then subtract that from the "QTY" to create a calculated field called "QtyLeft".
The result would basically look like "SELECT PO, Qty, answerToThisQuestion AS QtyLeft FROM labelDrops"

Start by creating a query which gives you the count for each PO in your imageLiveCount table:
SELECT i.PO, Count(*) AS CountOfInstances
FROM imageLiveCount AS i
GROUP BY i.PO
If that query returns what you want, join it to the labelDrops table and compute QtyLeft:
SELECT
l.PO,
l.Qty,
(l.Qty - sub.CountOfInstances) AS QtyLeft
FROM
labelDrops AS l
INNER JOIN
(
SELECT i.PO, Count(*) AS CountOfInstances
FROM imageLiveCount AS i
GROUP BY i.PO
) AS sub
ON l.PO = sub.PO

Related

How can I parse a string value in one table to join with values in another table

I have an issue where to create a report, I need two tables to join that don't have any way to join. I did find a way they could potentially join, but it's complicated.
There is table A, which contains a column called select_criteria. Here are some examples of 3 values it contains:
SELECT DISTINCT SUM(TRANSCRIPTDETAIL.CREDIT_BILLING) FROM SOMETABLE WHERE (( STUDENTFINANCIAL.TUITION_EXEMPTION = 'EMPFT' ) OR ( STUDENTFINANCIAL.TUITION_EXEMPTION = 'EMPPT' )))
SELECT DISTINCT SUM(TRANSCRIPTDETAIL.CREDIT_BILLING) FROM SOMETABLE WHERE ( STUDENTFINANCIAL.TUITION_EXEMPTION = 'PART50' )
In table B, I have a column called tuition_exemption, which contains values like:
EMPFT
EMPPT
PART50
At the tail end of the whole value within the column in table A, there are the tuition exemption codes that match the values in table B.
Is there a way using MSSQL where I can parse out the codes from the long statement in select_criteria, so that they perfectly match the codes from table B? This is my thought on a way to join up table A and table B like I need to do. The other complication is that there is a 1:many connection between select_criteria and a tuition_exemption value, but a 1:1 connection between a tuition_exemption value and a select_criteria value.
So in the end, the join between the two tables should print, in one example, the same select_criteria value twice (I am referencing the first value in my list above from table A), but in those two rows, the two different tuition_exemption values (EMPFT and EMPPT). Or in the case of table A example 2, it would be printed once and match up to PART50 once.
I am stuck here. I have a statement that successfully grabs the select_criteria values I want:
SELECT select_criteria
WHERE (
select_criteria LIKE '%EMPFT%' OR
select_criteria LIKE '%EMPPT%' OR
select_criteria LIKE '%PART50%' OR
)
But what I need to do is this. When it grabs the select_criteria values I want, I then want to print to a new column in this table the code it matches up to. Those codes are values in table B like 'EMPFT', 'EMPPT' and 'PART50'. That is why I was thinking of basically parsing out the codes from select_criteria, and printing them into the new column in table A. That way table A and table B have a value to match up on and I write run my report. I just don't now how to do it in SQL. I kind of know in Perl, but was hoping to just do all of this in SSMS 2012.
Thanks for any help!
byobob
You can use any expression which returns a boolean as a join criteria. Since LIKE returns a bool, you should be able to just do this:
select *
from tableA
join tableB
on tableA.select_criteria like '%' + tableB.codecolumn + '%'

Subquery with GROUPBY on calculated field: Your query does not include the specified expression '' as part of an aggregate function

I get the following error message
"Your query does not include the specified expression 'SampleCode' as part of an aggregate function."
I've looked into aggregate functions and have tried various ways to GROUP BY using the individual data fields that make up the code but I can't seem to get anything to work.
'SampleCode' is a concatenated query field (query name: datqry_SampleNumber) that is based on data from 3 different tables to create a unique value as follows...
SampleCode: IIf([tbl_Carcass.SampleNumber]="-999","-999",
"NPT-" & [tbl_SurveyInfo.SurveyYear*] & "-" &
[datqry_TransectData.Project_Code] & "-" & [tbl_Carcass.SampleNumber])
for SampleNumber values > 0001 (-999 is a placeholder indicating no SampleNumber assigned). Note, SurveyYear* is a calculated field based on the SurveyDate data field.
So, since SampleCode needs to be unique to each sample, I am trying to build a duplicate query, based on the aforementioned query, to identify duplicate SampleCodes so they can be relabeled and archived w/ a unique qualifier. The criteria for the duplicate query operation is as follows
In (SELECT [SampleCode] FROM [datqry_SampleNumber] As Tmp
GROUP BY [SampleCode] HAVING Count(*)>1 )
Any ideas on how to tackle this problem? Thank you in advance for your help and suggestions.
This looks like it might be a limitation of the JET engine used by Access to interpret its SQL.
It appears to be having trouble working with the subquery because it contains an aggregation of a calculated field (SampleCode in your case).
Try saving this as a separate query called, e.g. qryDuplicates:
SELECT [SampleCode] FROM [datqry_SampleNumber]
GROUP BY [SampleCode] HAVING Count(*)>1;
Then what you are trying to do will work as expected:
SELECT * from someTable WHERE someField IN (
SELECT * FROM qryDuplicates
);
TECHNICAL NOTE: I've tested it out and it is indeed specific to the fact that SampleCode is a calculated field. Doing exactly the same kind of grouped subquery works as expected when the field in question is not calculated.
With this test database this query works:
SELECT * FROM Table2 WHERE Field3 IN (
SELECT Field1 FROM datqry_SampleNumber
GROUP BY Field1 HAVING COUNT(*) > 1
);
And this doesn't
SELECT * FROM Table2 WHERE Field3 IN (
SELECT SampleCode FROM datqry_SampleNumber
GROUP BY SampleCode HAVING COUNT(*) > 1
);

Compare tables and Find the missing records

I am trying to compare a table T1 and a view v1 and find the missing records from the table T1 and display the results in a excel when a button is clicked. I am trying the wrap up the situation into a stored procedure and call it from vba code. I am not sure on how to start this.. The field names are different in both the tables, although it has same data. Any help will be much appreciated. I have tried many code samples , but I didn't achieve what I want..
Table T1
alpha.FileID
Master Policy Number
Insurance Name
View V1
FileID
PolNO
InsName
These are the few columns. Though, they have different field names, the data are the same. Some times the records are missing in the table v1, and I need to compare the two tables and find the missing records of the table v2.
SELECT View_v1.[Insured Name]
FROM View_v1
WHERE View_v1.alpha.FileID NOT IN
(
SELECT Table_t1.FileID
FROM Table_t1
)
An except clause is the easiest way to do this:
SELECT FileID, PolNO, InsName
FROM View V1
EXCEPT
SELECT FileID, MasterPolicyNumber, InsuranceName
FROM Table T1
This will give you the rows in the first select that do not exist in the second select (depending on your desired results you might flip the top and bottom selects). As long as the data types and number of columns are the same, the name of each field doesn't matter. Your result set will show the field names of the first select.
Also since you didn't specify your dbms, "MINUS" is used instead of "EXCEPT" for some dbms's like Oracle.
I believe this is what you're looking for based on your description.
I'm comparing every field, not just FileID as your example appears to be attempting. So, if you truly want to look only for missing FileIDs, just remove the other join on conditions.
SELECT View_v1.FileID, View_v1.PolNO, View_v1.InsName
FROM View_v1
LEFT JOIN Table_t1
on View_v1.FileID = Table_t1.FileID
and View_v1.PolNO = Table_t1.[Master Policy Number]
and View_v1.InsName = Table_t1.[Insurance Name]
WHERE Table_t1.FileID is null

SQL loop through a table and find the next part record

Not sure where to start on this one. I inheriated a table that has a list of part numbers that are are active and inactive. If the part number is inactive, they enter the next valid part number. If the part number is active there is no Next PartNumber. They want to search on a Part Number and find all of the next part numbers that match.
Basically the table looks like this.
PartNumber Varchar(20), Active Varchar(3), NextPartNumber Varchar(20).
Problem is I do not know how many part numbers are in the chain. Here is a sample of the data:
100X No XYZ
XYZ No 45A6
45A6 Yes
QWER No RT98
RT98 No POUL1
POUL1 No N9HGT
N9HGT No FGH12
FGH12 Yes
I can write a query like this, but since I don't know how many part numbers there are, this won't work.
Select A.PartNumber, A.NextPartNumber, B.PartNumber, B.NextPartNumber, C.PartNumber, C.NextPartNumber
FROM tblPartTable as A
inner join
tblPartTable as B
on A.PartNumber = B.NextPartNumber
inner join
tblPartTable as C
on B.PartNumber = C.NextPartNumber
where A.PartNumber = '100X'
With SQL Server (which I'm assuming you're talking about since your earlier questions have been about it), you can use a recursive common table expression to easily get the searched for part and all its successors, there is no need to loop manually;
WITH cte AS (
-- Base condition, where do we start the search?
SELECT t.* FROM tblPartTable t WHERE t.PartNumber = '100X'
UNION ALL
-- Continue condition, how do we find the next part from the current one?
SELECT t.* FROM tblPartTable t JOIN cte ON t.PartNumber = cte.NextPartNumber
)
SELECT partnumber, active FROM cte;
An SQLfiddle to test with.
The same query works on most RDBMS's except MySQL.

SQL statement to return data from a table in an other sight

How would the SQL statement look like to return the bottom result from the upper table?
The last letter from the key should be removed. It stands for the language. EXP column should be split into 5 columns with the language prefix and the right value.
I'm weak at writing more or less difficult SQL statements so any help would be appreciated!
The Microsoft Access equivalent of a PIVOT in SQL Server is known as a CROSSTAB. The following query will work for Microsoft Access 2010.
TRANSFORM First(table1.Exp) AS FirstOfEXP
SELECT Left([KEY],Len([KEY])-2) AS [XKEY]
FROM table1
GROUP BY Left([KEY],Len([KEY])-2)
PIVOT Right([KEY],1);
Access will throw a circular field reference error if you try to name the row heading with KEY since that is also the name of the original table field that you are deriving it from. If you do not want XKEY as the field name, then you would need to break apart the above query into two separate queries as shown below:
qsel_table1:
SELECT Left([KEY],Len([KEY])-2) AS XKEY
, Right([KEY],1) AS [Language]
, Table1.Exp
FROM Table1
ORDER BY Left([KEY],Len([KEY])-2), Right([KEY],1);
qsel_table1_Crosstab:
TRANSFORM First(qsel_table1.Exp) AS FirstOfEXP
SELECT qsel_table1.XKEY AS [KEY]
FROM qsel_table1
GROUP BY qsel_table1.XKEY
PIVOT qsel_table1.Language;
In order to always output all language columns regardless of whether there is a value or not, you need to spike of those values into a separate table. That table will then supply the row and column values for the crosstab and the original table will supply the value expression. Using the two query solution above we would instead need to do the following:
table2:
This is a new table with a BASE_KEY TEXT*255 column and a LANG TEXT*1 column. Together these two columns will define the primary key. Populate this table with the following rows:
"AbstractItemNumberReportController.SelectPositionen", "D"
"AbstractItemNumberReportController.SelectPositionen", "E"
"AbstractItemNumberReportController.SelectPositionen", "F"
"AbstractItemNumberReportController.SelectPositionen", "I"
"AbstractItemNumberReportController.SelectPositionen", "X"
qsel_table1:
This query remains unchanged.
qsel_table1_crosstab:
The new table2 is added to this query with an outer join with the original table1. The outer join will allow all rows to be returned from table2 regardless of whether there is a matching row in the table1. Table2 now supplies the values for the row and column headings.
TRANSFORM First(qsel_table1.Exp) AS FirstOfEXP
SELECT Table2.Base_KEY AS [KEY]
FROM Table2 LEFT JOIN qsel_table1 ON (Table2.BASE_KEY = qsel_table1.XKEY)
AND (Table2.LANG = qsel_table1.Language)
GROUP BY Table2.Base_KEY
PIVOT Table2.LANG;
Try something like this:
select *
from
(
select 'abcd' as [key], right([key], 1) as id, expression
from table1
) x
pivot
(
max(expression)
for id in ([D], [E])
) p
Demo Fiddle