How to Take two SQL queries of a column of substrings to search database using the appended result of the other - sql

I have two select statements that both contain a column of substrings that derived from a database table. They are substrings derived from a varchar that should be an XML, but were saved as varcars because they could be not well-formed and potentially invalid.
I am trying to take the table that results in the 1st query, a list of 50 Varchars, and search the database using the 2nd query. I could get from 0 to n SQLRelatesMessageID sets from each SQLmessageID if I use each row in the first query and append a string to get the node ("z4480" is an example here).
I have tried a cursor implementation but the performance detered me from finishing it. Join doesn't work if you try giving the substring column with an as alias. What steps should I do to get the overall list of SQLRelatesMessageIDs. My goal is to get all MessageLogId (3 in picture) given a NCPDPID.
I am using SQL Server Manager 2012.
--1--Recieves a list based on a given NCPDPID node Value
select substring(m.message, charindex('<MessageID>', m.message)+11, charindex('</MessageID>', m.message)-charindex('<MessageID>', m.message)-11) as
SQLmessageID from messagelog m where message like '%<NCPDPID>'+'1234567'+'</NCPDPID>%'
--2--Selects messageID from top select and searches RelatesToMessageID node
select substring(r.message, charindex('<RelatesToMessageID>', r.message)+20, charindex('</RelatesToMessageID>', r.message)-charindex('<RelatesToMessageID>', r.message)-20) as SQLRelatesMessageID, * from messagelog r
where message like ('%<RelatesToMessageID>'+'z4480'+'</RelatesToMessageID>%')

This works for this answer.
---main
SELECT * FROM
(
select substring(m.message, charindex('<MessageID>', m.message)+11, charindex('</MessageID>', m.message)-charindex('<MessageID>', m.message)-11) as SQLmessageID from messagelog m
where message like '%<NCPDPID>1234567</NCPDPID>%' and dateTime > '3/01/2016'
) a JOIN
(
select
substring(r.message, charindex('<RelatesToMessageID>', r.message)+20, charindex('</RelatesToMessageID>', r.message)-charindex('<RelatesToMessageID>', r.message)-20) as SQLRelatesMessageID,
message,
messagelogid from messagelog r
where
dateTime > '3/01/2016' AND
message LIKE ('%<RelatesToMessageID>%</RelatesToMessageID>%')
) b ON b.SQLRelatesMessageID = a.SQLmessageID

Related

How to join 2 tables with multiple conditions each?

I have data split between 2 tables, and need to join the necessary data together for analysis.
One table Test 3 Output contains ID numbers, and the return value of the test. The other table Test Results contains the same IDs, along with their corresponding serial number and overall test result.
I need to combine these into a single table that just displays ID, serial number and test value.
Sorry in advance for the horrible SQL thats about to follow, I'm brand new to this.
I have 2 working queries that give me what I want, but I can't seem to join them together.
The first query:
select `ID`,`Serial Number` from `Test Results`t where (len(`Serial Number`)=16 and FailMode = '24V Supply FAIL')
This gets me the ID and serial number of all the tests that failed '24V supply'. It also filters out garbage serial numbers as the correct ones should have 16 digits.
The second query:
select `ID` from `Test 3 Output`o where o.`24V Supply (V)`<30
This gets me the ID and test results, and filters out some results that were greater than 30V. Note that '24V Supply(V) is the name of the column containing the test results.
Now when I try to join these with the ID, I get a syntax error. Here's what I tried:
select `ID`,`Serial Number`
from `Test Results`t
where (len(`Serial Number`)=16 and FailMode = '24V Supply FAIL')
left join (`Test 3 Output`o ON t.`ID` = o.`ID` where o.`24V Supply (V)`<30)
This gives the error:
Error: Syntax error (missing operator) in query expression (len(`Serial Number`)=16 and FailMode = '24V Supply FAIL') left join (`Test 3 Output`o ON t.`ID` = o.`ID` where o.`24V Supply (V)`<30)
I'm not sure what operator I'm missing but I had a feeling its related to the fact there's two where statements?
Can anyone offer some help?
Edit: I found a workaround since I can't use 2 where clauses with a join. I created 2 views with my 2 separate queries, and performed the join on those which got me what I wanted. I'd still like to hear a proper way of doing it though :)
You can join 2 subqueries like this:
SELECT q1.a, q1.b, q2.c
FROM (
(SELECT a, b FROM table1
WHERE b > 10) AS q1
LEFT JOIN
(SELECT a, c FROM table2
WHERE c > 20) AS q2
ON q1.a = q2.a
)
Doing the subqueries as separate query objects is easier to debug, but the query objects keep piling up...

SQL Server 2012 Filtering Results Based on One Table and Appending Info

I've been trying to search for a similar query on stackoverflow to modify to get what I need but I can't seem to get it right. I hope someone here can help.
I have two tables located in two different databases. Both databases are configured on the same server. Table 1 called 'DiscreteLive' and located in Database 'Runtime'. Table 2 is called 'v_DiscreteHistory' and located in Database 'WWALMDB'.
They have the following fields
DiscreteLive
Tagname (type String)
Value (type Integer --> can only ever be 1 or 0)
'v_DiscreteHistory'
Tagname (type String)
Value (type String --> can only ever be true of false)
EventStamp (type datetime)
Description (type String)
The 'DiscreteLive' table can only ever have one unique tagname line. An external software will overwrite to each tagname's corresponding Value field. It's basically showing the live values of the system. Example shown below. For example, you would never find Device1.Commfail twice in this table.
Device1.Commfail
Device1.Auto
Device1.Man
Device2.Commfail
Device2.Auto
Device2.Man
Device3.Commfail
Device3.Auto
Device3.Man
Device4.commfail
Device4.Auto
Device4.Man
Device5.Commfail
Device5.Auto
Device5.Man
etc.
The 'v_DiscreteHistory' table is the history of the specific tag. There can be multiple entries of the same tag along with its Description and EventStamp (Time the even happened).
What I'm trying to do is to filter out the 'DiscreteLive' table to show only the tag values where the tagname is a %.CommFail and the Value is 1. Then I would like to take the result of that initial query and attach the latest EventStamp and Description for those tags in the initial query from 'v_DiscreteHistory'.
Not sure if this can be done. Let me know if you need more clarification.
SQL Server: This might be what you are looking for
SELECT
D.TagName
,D.Value
,V.Tagname
,V.Value,V.EventStamp
,V.Description
,MAX(V.EventStamp) AS 'LatestDate'
FROM
SERVER.Runtime.dbo.DiscreteHistory D
INNER JOIN
SERVER.WWALMDB.dbo.v_DiscreteHistory V
ON
D.Tagname = V.Tagname
WHERE
D.Value = 1
AND
V.Value LIKE '%.CommFail'
GROUP BY
D.TagName
,D.Value
,V.Tagname
,V.Value,V.EventStamp
,V.Description

SQL returns the unique identifier instead of the value in my Access UNON ALL SQL

So here is my project using MS Access 2010,
I have developed 2 queries to select 2 different reading periods. These queries are called CycleStart and CycleEnd. When I run these 2 queries individually I get expected output results. these 2 queries pull data from tables with a couple lookup fields in them. So the lookup fields use other tables where there are only 2 columns. The next step I use SQL to create a UNION ALL query to bring these 2 cycle queries together for reporting purposes. The problem I run into is that my resulting Union query does not output the same information as the 2 individual cycle queries.
Now the specific issues. My cycle queries have a couple lookup fields referencing another table. For example the Read_Cycle field comes for a table(Read_Cycles) and only has 2 columns, the unique identifer assigned by Access and the Read_Cycle column with the data I enter. When I run the cycle queries the field for Read_Cycle returns the Read_Cycle data as expected, but the union query does not. So here is some structure of my project:
Read_Cycles Table
|ID Col1 | |Cycle_ID Col2|
1 Spring
2 Fall
3 Winter
The data tables behind the CycleStart and the CycleEnd have fields that are lookup values referencing the above described Read_Cycles table.
Query CycleStart and CycleEnd return Spring or fall or winter, which ever value is associated with the record, correctly.
however, the problem I have is that the Union SQL Query returns the ID instead of the value, so instead of getting Fall, I get the 2.
Here is my UNION ALL SQL........
SELECT "CycleEnd" AS source,
[CycleEnd].[Recloser_SerialNo],
[CycleEnd].[Read_Date],
[CycleEnd].[3_Phase_Reading],
[CycleEnd].[A_Phase_Reading],
[CycleEnd].[B_Phase_Reading],
[CycleEnd].[C_Phase_Reading],
[CycleEnd].[Read_Cycle],
[CycleEnd].[PoleNo],
[CycleEnd].[Substation],
[CycleEnd].[Feeder],
[CycleEnd].[Feeder_Description],
[CycleEnd].[Recloser_Location]
FROM [CycleEnd]
UNION ALL
SELECT "CycleStart" AS source,
[CycleStart].[Recloser_SerialNo],
[CycleStart].[Read_Date],
[CycleStart].[3_Phase_Reading] * - 1,
[CycleStart].[A_Phase_Reading] * - 1,
[CycleStart].[B_Phase_Reading] * - 1,
[CycleStart].[C_Phase_Reading] * - 1,
[CycleStart].[Read_Cycle],
[CycleStart].[PoleNo],
[CycleStart].[Substation],
[CycleStart].[Feeder],
[CycleStart].[Feeder_Description],
[CycleStart].[Recloser_Location]
FROM [CycleStart];
All other fields are coming across just fine and as expected, I have narrowed it down to only fields that are a lookup in the original tables.
Any help would be greatly appreciated. Also my SQL experience is really limited so example code would help greatly.
UPDATE:
here is the sql from the CycleEnd that works. I got this by building the query then changing to the SQL view...
SELECT Recloser_Readings.Recloser_SerialNo,
Recloser_Readings.Read_Date,
Recloser_Readings.[3_Phase_Reading],
Recloser_Readings.A_Phase_Reading,
Recloser_Readings.B_Phase_Reading,
Recloser_Readings.C_Phase_Reading,
Recloser_Locations.PoleNo,
Recloser_Locations.Substation,
Recloser_Locations.Feeder,
Recloser_Locations.Feeder_Description,
Recloser_Locations.Recloser_Location,
Recloser_Readings.Read_Cycle
FROM (
Recloser_Inventory LEFT JOIN Recloser_Locations
ON Recloser_Inventory.PoleNo = Recloser_Locations.PoleNo
)
RIGHT JOIN Recloser_Readings
ON Recloser_Inventory.Serial_No = Recloser_Readings.Recloser_SerialNo
WHERE (((Recloser_Readings.Read_Cycle) = "8"));
UPDATE#2
I noticed I grabbed the wrong code that references the Read_Cycles table. Here it is...
SELECT Read_Cycles.Cycle_ID, Read_Cycles.ID
FROM Read_Cycles
ORDER BY Read_Cycles.Cycle_ID DESC;
UPDATE : SYNTAX ERROR FROM THE FOLLOWING CODE!!
SELECT "CycleEnd" as source,
[CycleEnd].[Recloser_SerialNo],
[CycleEnd].[Read_Date],
[CycleEnd].[3_Phase_Reading],
[CycleEnd].[A_Phase_Reading],
[CycleEnd].[B_Phase_Reading],
[CycleEnd].[C_Phase_Reading],
[CycleEnd].[Read_Cycle],
[CycleEnd].[PoleNo],
[CycleEnd].[Substation],
[CycleEnd].[Feeder],
[CycleEnd].[Feeder_Description],
[CycleEnd].[Recloser_Location]
FROM [CycleEnd] JOIN [Read_Cycles] ON [CycleEnd].[Read_Cycle] = [Read_Cycles].[ID]
UNION ALL SELECT "CycleStart" as source,
[CycleStart].[Recloser_SerialNo],
[CycleStart].[Read_Date],
[CycleStart].[3_Phase_Reading]*-1,
[CycleStart].[A_Phase_Reading]*-1,
[CycleStart].[B_Phase_Reading]*-1,
[CycleStart].[C_Phase_Reading]*-1,
[CycleStart].[Read_Cycle],
[CycleStart].[PoleNo],
[CycleStart].[Substation],
[CycleStart].[Feeder],
[CycleStart].[Feeder_Description],
[CycleStart].[Recloser_Location]
FROM [CycleStart] JOIN [Read_Cycles] ON [CycleStart].[Read_Cycle] = [Read_Cycles].[ID];

Invalid Column Name in SQL Server Management Studio

When I execute this query in SQL Server Management Studio, this error appears:
'Msg 207, Level 16, State 1, Line 1
Invalid column name 'ACCOUNT_NO'.'
This is the code for the query:
DECLARE #largeaccnumber INT = ACCOUNT_NO
DECLARE #smallaccnumber INT
SET #smallaccnumber = (SELECT LEFT(#largeaccnumber, 6))
SELECT DNADRX.CODE,
DNADDR.NAME,
DNADDR.TYPE,
DNADDR.MAIL_NAME,
ADDRESS_LINE1,
ADDRESS_LINE2,
ADDRESS_LINE3,
TOWN_CITY,
COUNTY_STATE,
COUNTY_STATE_CODE,
COUNTRY,
POST_ZIP,
LAST_STAT_DATE,
ACCOUNT_NO
FROM DNADRX,
DNADDR,
BACCNT
WHERE DNADDR.CODE = DNADRX.ADDRESS_CODE
AND DNADDR.CODE = #smallaccnumber
ORDER BY DNADRX.CODE
I want the query to display the data from the columns of the different tables (the columns are listed in the SELECT bit of the query) from 3 different tables (DNADRX, DNADDR, BACCNT), and the factor linking all 3 tables together is the 6 digit code (ACCOUNT_NO in the BACCNT table, ADDRESS_CODE in the DNADRX table and CODE in the DNADDR table). Originally, ACCOUNT_NO from table BACCNT was 8 digits long, but I reduced it to the first 6 digits using SELECT LEFT and assigned this 6 digit value to the variable #smallaccnumber.
Whenever I try to execute the query, it keeps telling me that 'ACCOUNT_NO' is an invalid code name. I have checked the spelling, refreshed using IntelliSense and tried 'BACCNT.ACCOUNT_NO' instead of just 'ACCOUNT_NO' on the first line of the query but it still won't work (instead it says that the multi-part identifier could not be bound when I try 'BACCNT.ACCOUNT_NO').
I am really new to SQL coding so sorry if the answer to my problem is really simple.
Thank you for your assistance :)
You can try something like this.
This assumes you know the 6 character code. This query will only find results IF there is a record matching in EVERY table. If one table doesn't find a matching record this query will return NOTHING. If you want to find a row even if a recrod is missing from a table, replace the "INNER JOIN" with "LEFT OUTER JOIN"
SELECT Dnadrx.Code,
Dnaddr.Name,
Dnaddr.Type,
Dnaddr.Mail_Name,
Address_Line1,
Address_Line2,
Address_Line3,
Town_City,
County_State,
County_State_Code,
Country,
Post_Zip,
Last_Stat_Date,
Account_No
FROM Dnaddr
INNER JOIN BACCNT ON DNAADDR.CODE = BACCNT.ACCOUNT_NO
INNER JOIN Dnadrx ON Dnaaddr.Code=Dnaadrx.Address_Code
WHERE Dnaddr.Code='YOUR 6 CHARACTER CODE GOES HERE'
ORDER BY Dnadrx.Code;

Help with a complex join query

Keep in mind I am using SQL 2000
I have two tables.
tblAutoPolicyList contains a field called PolicyIDList.
tblLossClaims contains two fields called LossPolicyID & PolicyReview.
I am writing a stored proc that will get the distinct PolicyID from PolicyIDList field, and loop through LossPolicyID field (if match is found, set PolicyReview to 'Y').
Sample table layout:
PolicyIDList LossPolicyID
9651XVB19 5021WWA85, 4421WWA20, 3314WWA31, 1121WAW11, 2221WLL99 Y
5021WWA85 3326WAC35, 1221AXA10, 9863AAA44, 5541RTY33, 9651XVB19 Y
0151ZVB19 4004WMN63, 1001WGA42, 8587ABA56, 8541RWW12, 9329KKB08 N
How would I go about writing the stored proc (looking for logic more than syntax)?
Keep in mind I am using SQL 2000.
Select LossPolicyID, * from tableName where charindex('PolicyID',LossPolicyID,1)>0
Basically, the idea is this:
'Unroll' tblLossClaims and return two columns: a tblLossClaims key (you didn't mention any, so I guess it's going to be LossPolicyID) and Item = a single item from LossPolicyID.
Find matches of unrolled.Item in tblAutoPolicyList.PolicyIDList.
Find matches of distinct matched.LossPolicyID in tblLossClaims.LossPolicyID.
Update tblLossClaims.PolicyReview accordingly.
The main UPDATE can look like this:
UPDATE claims
SET PolicyReview = 'Y'
FROM tblLossClaims claims
JOIN (
SELECT DISTINCT unrolled.LossPolicyID
FROM (
SELECT LossPolicyID, Item = itemof(LossPolicyID)
FROM unrolling_join
) unrolled
JOIN tblAutoPolicyList
ON unrolled.ID = tblAutoPolicyList.PolicyIDList
) matched
ON matched.LossPolicyID = claims.LossPolicyID
You can take advantage of the fixed item width and the fixed list format and thus easily split LossPolicyID without a UDF. I can see this done with the help of a number table and SUBSTRING(). unrolling_join in the above query is actually tblLossClaims joined with the number table.
Here's the definition of unrolled 'zoomed in':
...
(
SELECT LossPolicyID,
Item = SUBSTRING(LossPolicyID,
(v.number - 1) * #ItemLength + 1,
#ItemLength)
FROM tblLossClaims c
JOIN master..spt_values v ON v.type = 'P'
AND v.number BETWEEN 1 AND (LEN(c.LossPolicyID) + 2) / (#ItemLength + 2)
) unrolled
...
master..spt_values is a system table that is used here as the number table. Filter v.type = 'P' gives us a rowset with number values from 0 to 2047, which is narrowed down to the list of numbers from 1 to the number of items in LossPolicyID. Eventually v.number serves as an array index and is used to cut out single items.
#ItemLength is of course simply LEN(tblAutoPolicyList.PolicyIDList). I would probably also declared #ItemLength2 = #ItemLength + 2 so it wasn't calculated every time when applying the filter.
Basically, that's it, if I haven't missed anything.
If the PolicyIDList field is a delimited list, you have to first separate the individual policy IDs and create a temporary table with all of the results. Next up, use an update query on the tblLossClaims with 'where exists (select * from #temptable tt where tt.PolicyID = LossPolicyID).
Depending on the size of the table/data, you might wish to add an index to your temporary table.