Can't get unique values joining two tables - sql

I have 2 tables that I need to join and select the unique rows from. Here is a sample of my data: (there are more columns)
tbl1:
MB# MBName PCCNo_PRI Primary_IP PCCNo_SEC Secondary_IP ID
100 name 0 10.1.9.10 30 10.1.9.10 1
103 name3 17 10.1.9.27 47 10.1.9.67 4
403 name13 17 10.1.9.27 47 10.1.9.67 14
tbl2:
RTU PCC#_PRI PCC#_SEC STATION ADDRESS
15 0 30 6
52 12 42 1
53* 17 47 1
54 18 48 1
63 9 39 2
69* 17 47 2
I need to join the two tables and get the unique RTU(s) in tbl2 for a given MB# in tbl1.
Query =
SELECT t1.MB#,t2.RTU,t2.[Device Manufacturer],t2.PCC#_PRI,t2.PCC#_SEC,t2.[STATION ADDRESS]
INTO C300_RTU_MASTERBLK_Map
FROM mbm_PCDIMasterBlk_tbl as t1, dbo.WOA_PCC_Conn_tbl as t2
WHERE t1.PCCNo_PRI = t2.PCC#_PRI
I am getting duplicate rows for tbl2 53 and 69 (* above). 53 ends up with 2 entries; one to 103 and one 403 (69 gets same). How can I query this for unique RTU(s) to MB#?

The duplicate rows appears because you join on "17" which gives 2 rows on each side
Then, as it stands, you can't with that SELECT list.
How do you decide which t1.MB# you want for the t2 columns?
There is no secondary JOIN column that I can see.
So the best you can get is use MAX (or MIN) to pick either 403 or 103.
SELECT
MAX(t1.MB#) AS MB#,
t2.RTU,t2.[Device Manufacturer],t2.PCC#_PRI,t2.PCC#_SEC,t2.[STATION ADDRESS]
INTO C300_RTU_MASTERBLK_Map
FROM
dbombm_PCDIMasterBlk_tbl as t1
JOIN
dbo.WOA_PCC_Conn_tbl as t2 ON t1.PCCNo_PRI = t2.PCC#_PRI
GROUP BY
t2.RTU,t2.[Device Manufacturer],t2.PCC#_PRI,t2.PCC#_SEC,t2.[STATION ADDRESS]

Related

I have a table fetching values from an SP. I'd like to know if a combination of data is reversely repeated

I have a table named #hierachy, for which there are three columns:
childId, parentId, and linkType
The data is as follows:
childID parentID linktype
30 31 53
31 42 56
31 415349 18
31 437327 18
31 438333 18
35 32 56
32 35 18
32 38 52
32 39 52
32 439395 51
34 40 51
I'd like to spot any reverse repetitions and return a "true" or "1" if there is a reverse repetition between the first two columns childID and parentID
For example, the sixth and seventh lines are reversely similar: One is 35 then 32 and the other is the reverse: 32 and 35.
Thank you!
You can use exists:
select t.*,
(case when exists (select 1
from t t2
where t2.childID = t.parentID and t2.parentID = t.childID
)
then 1 else 0
end) as is_reversed
from t;
If the data is being returned from a stored procedure, you need to either put this logic in the stored procedure or put the data into a table and run the logic using that table.

how to join two tables using wildcards giving only best match per row from table1

How can I limit the results of a query that uses a wildcard join between two tables to only one result (best match) per row from table 1?
I've got the following data structures:
table t1:
ID AccountStr
1 7
2 71
3 72
4 721
5 73
6 8
table t2:
ID AccountPattern AccountType
1 7 Type01
2 72 Type02xxx
desired query result:
Line AccountStr AccountType
1 7 Type01
2 71 Type01
3 72 Type02xxx
4 721 Type02xxx
5 73 Type01
6 8 NULL
code I used (Syntax: MS Access SQL):
SELECT T1.AccountStr, T2.AccountType
FROM T1 LEFT JOIN T2 ON T1.AccountStr Like T2.AccountPattern+"*"
ORDER BY T1.AccountStr, T2.AccountType;
result of my query, unwanted lines marked:
Line AccountStr AccountType
1 7 Type01
2 71 Type01
3 72 Type01 **unwanted line**
4 72 Type02xxx
5 72 Type01 **unwanted line**
6 721 Type02xxx
7 73 Type01
8 8 NULL
I understand, why my query gives all matches - 72 matches pattern 7* - but since there is a better matching pattern 72* I need to only get that one in my results.
I thought about a descending sort order of t2 - AccountPattern 72 before 7 - and limiting pattern match results to first row only, but I don't know how to do that - or maybe ther's a better approach.
Use a correlated subquery with TOP 1:
SELECT T1.AccountStr,
(SELECT TOP 1 T2.AccountType
FROM T2
WHERE T1.AccountStr Like T2.AccountPattern + "*"
ORDER BY LEN(T2.AccountPattern) DESC, T2.AccountPattern
) as AccountType
FROM T1
ORDER BY T1.AccountStr;
This returns the longest matching pattern.

How to find a specific value in consecutive date

I need your help for a little issue.
I use MS ACCESS to work with a database and I need to resolve a query. My query asks:
Find the CUSTOMER_ID and TRANSC_ID where 2 consecutive value between 200 and 500 WITHIN the same transc_id.
I explain.
I have this table in this format:
CUSTOMER_ID TRANSC_ID VALUE VALUE_DATE
51 10 15 29-12-1999
51 10 20 15-07-2000
51 10 35 18-08-2000
51 10 250 30-08-2000
51 10 13 10-09-2000
51 10 450 15-09-2000
51 11 5 15-09-2000
51 11 23 30-09-2000
51 11 490 10-10-2000
51 11 300 12-10-2000
51 11 85 30-10-2000
51 11 98 01-01-2000
53 10 65 15-10-2000
53 10 14 29-12-2000
And I need just
51 11 490 10-10-2000
51 11 300 12-10-2000
because the two values is consecutive (and both of them is >250 and <500).
How can I make a query in MS ACCESS to obtain this result?
Thank you.
You can get the "next" and "previous" values using correlated subqueries, and then do the comparison:
select t.*
from t
where t.value between 200 and 500 and
( (select top 1 t2.value
from t as t2
where t2.CUSTOMER_ID = t.CUSTOMER_ID and t2.TRANSC_ID = t.TRANSC_ID and
t2.value_date > t.value_date
order by t2.value_date
) between 200 and 500 or
(select top 1 t2.value
from t as t2
where t2.CUSTOMER_ID = t.CUSTOMER_ID and t2.TRANSC_ID = t.TRANSC_ID and
t2.value_date < t.value_date
order by t2.value_date desc
) between 200 and 500
);

Postgresql: append two tables with different columns

I would like to append one table to the other; both tables may have different columns. The result should be a table with all columns and where values do not exist, it should be a missing observation. The data are time series - which I am getting from different sources due to time span constraints - so I need to "stack" them on each other, but it could be that one or the other column is added or dropped off.
As there is a little overlap in the rows I am looking for a solution that would take the data of first table. The problem is then for those column not existing in table 1, they wouldn't exist either when I pick table 1 over table 2.
Current solution is to cut-off table 2 so there is no overlap.
table 1:
date AA BB CC DD
20100101 9 10 11 12
20100102 10 11 12 13
table 2:
date AA BB CC EE FF
20100102 99 99 10
20100103 11 12 13 14 10
20100104 12 13 14 15 11
and the result should be
date AA BB CC DD EE FF
20100101 9 10 11 12
20100102 10 11 12 13 99 10
20100103 11 12 13 14 10
20100104 12 13 14 15 11
So I do not in fact have anything to "join" on as suggested here: SQL union of two tables with different columns
coalesce function may be used like in the following :
select coalesce(t1.date,t2.date) date,
coalesce(t1.aa,t2.aa) aa,
coalesce(t1.bb,t2.bb) bb,
coalesce(t1.cc,t2.cc) cc,
t1.dd,
t2.ee,
t2.ff
from table1 t1 full outer join table2 t2 on ( t1.date = t2.date );
SQL Fiddle Demo

SQL selecting values between two columns with a list

I'm attempting to find rows given a list of values where one of the values is in a range between two of the columns, as an example:
id column1 column2
1 1 5
2 6 10
3 11 15
4 16 20
5 21 25
...
99 491 495
100 496 500
I'd like to give a list of values, e.g. (23, 83, 432, 334, 344) which would return the rows
id column1 column2
5 21 25
17 81 85
87 431 435
67 331 335
69 341 345
The only way I can think of doing this so far has been to split each into it's own call by doing
SELECT * FROM TableA WHERE (column1 < num1 AND num1 < column2)
However this scales quite poorly when the list of numbers is around several million.
Is there any better way of doing this?
Thanks for the help.
Putting millions of numbers into the SQL command itself would be unwieldy.
Obviously, you have to put the numbers into a (temporary) table.
Then you can just join the two tables:
SELECT *
FROM TableA JOIN TempTable
ON TempTable.Value BETWEEN TableA.column1 AND TableA.column2;