SQL querying two sources - sql

I have a View and Table as example below
Table1
+---------+------+
| Country | City |
+---------+------+
| UK | LDN |
| US | NEY |
| US | LAX |
+---------+------+
View1
+---------+---------+-------+
| Column1 | Column2 | Site |
+---------+---------+-------+
| Test | Test2 | UKLDN |
| Test | Test2 | USNEY |
| Test | Test2 | USLAX |
| Test | Test2 | PELMA |
+---------+---------+-------+
The result i'm trying to achieve is show all rows from View1, that have a View1.Site column matching Table1.Country and Table1.City. My confusion is how do to it as i'm not an sql person but more C# etc.
The resulting data I want to create is below. I don't know if I can do this solely from View1 or what functions to use.
Result
+---------+---------+-------+---------------+
| Column1 | Column2 | Site | ExistInTable1 |
+---------+---------+-------+---------------+
| Test | Test2 | UKLDN | Y |
| Test | Test2 | USNEY | Y |
| Test | Test2 | USLAX | Y |
| Test | Test2 | PELMA | N |
+---------+---------+-------+---------------+
Thanks

You can try this.
SELECT V.*, CASE WHEN T.Country IS NULL THEN 'N' ELSE 'Y' END ExistInTable1 FROM View1 V
LEFT JOIN Table1 T ON V.Site = (T.Country + T.City)

This is T-SQL, but the format should be very similar for most other flavors of SQL.
SQL Fiddle
MS SQL Server 2014 Schema Setup:
CREATE TABLE Table1 (Country varchar(5),City varchar(5)) ;
INSERT INTO Table1 (Country,City)
VALUES ( 'UK','LDN'),('US','NEY'),('US','LAX')
;
CREATE TABLE View1 (Column1 varchar(10), Column2 varchar(10), Site varchar(10)) ;
INSERT INTO View1 (Column1,Column2,Site)
VALUES ('Test','Test2','UKLDN')
, ('Test','Test2','USNEY')
, ('Test','Test2','USLAX')
, ('Test','Test2','PELMA')
;
Query 1:
SELECT v.Column1, v.Column2
, CASE WHEN LEN(COALESCE(t.Country,t.City)) > 0 THEN 'Y' ELSE 'N' END AS ExistsInTable1
FROM View1 v
LEFT OUTER JOIN Table1 t ON v.Site = (t.Country+t.City)
Results:
| Column1 | Column2 | ExistsInTable1 |
|---------|---------|----------------|
| Test | Test2 | Y |
| Test | Test2 | Y |
| Test | Test2 | Y |
| Test | Test2 | N |

You need to do a LEFT JOIN with your table and then check if it matches or not with the info from the view, like this:
SELECT
VW.Column1
,VW.Column2
,VW.Site
,CASE WHEN ISNULL(T.country, T.city) IS NULL THEN 'N' ELSE 'Y' END AS ExistInTable1
FROM View1 VW
LEFT JOIN Table1 T
ON VW.site = CONCAT(T.country, T.City)
The LEFT JOIN keyword returns all records from the left table (View1), and the matched records from the right table (Table1). The result is NULL from the right side, if there is no match.(check done with the CASE statement)
You can test it Here as well.

Related

How can I subtract two row's values within same column using sql query in access?

(query access)
This is the table structure:
+-----+--------+--------+
| id | name | sub1 |
+-----+--------+--------+
| 1 | ABC | 6.27% |
| 2 | ABC | 7.47% |
| 3 | PQR | 3.39% |
| 4 | PQR | 2.21% |
+-----+--------+--------+
I want to subtract Sub1
Output should be:
+-----+--------+---------+------------------------------------+
| id | name | sub1 | |
+-----+--------+---------+------------------------------------+
| 1 | ABC | 6.27% | 0 First Rec no need Subtract |
| 2 | ABC | 7.47% | 1.2% <=(7.47-6.27) |
| 3 | PQR | 3.39% | 0 First Rec no need Subtract |
| 4 | PQR | 2.21% | -1.18% <=(2.21-3.39) |
+-----+--------+---------+------------------------------------+
Thank you so much.
If you can guarantee consecutive id values, then the following presents an alternative:
select t.*, nz(t.sub1-u.sub1,0) as sub2
from YourTable t left join YourTable u on t.name = u.name and t.id = u.id+1
Change YourTable to the name of your table.
This is painful, but you can do:
select t.*,
(select top 1 t2.sub1
from t as t2
where t2.name = t.name and t2.id < t.id
order by t2.id desc
) as prev_sub1
from t;
This gives the previous value or NULL for the first row. You can just use - for the subtraction.
An index on (name, id) would help a bit with performance. However, if you can upgrade to a better database, you can then just use lag().

Access Queries comparing two tables

I have two tables in Access, Table A and Table B:
Table MasterLockInsNew:
+----+-------+----------+
| ID | Value | Date |
+----+-------+----------+
| 1 | 123 | 12/02/13 |
| 2 | 1231 | 11/02/13 |
| 4 | 1265 | 16/02/13 |
+----+-------+----------+
Table InitialPolData:
+----+-------+----------+---+
| ID | Value | Date |Type
+----+-------+----------+---+
| 1 | 123 | 12/02/13 | x |
| 2 | 1231 | 11/02/13 | x |
| 3 | 1238 | 10/02/13 | y |
| 4 | 1265 | 16/02/13 | a |
| 7 | 7649 | 18/02/13 | z |
+----+-------+----------+---+
All I want are the rows from table B for IDs not contained in A. My current code looks like this:
SELECT Distinct InitialPolData.*
FROM InitialPolData
WHERE InitialPolData.ID NOT IN (SELECT Distinct InitialPolData.ID
from InitialPolData INNER JOIN
MasterLockInsNew
ON InitialPolData.ID=MasterLockInsNew.ID);
But whenever I run this in Access it crashes!! The tables are fairly large but I don't think this is the reason.
Can anyone help?
Thanks
or try a left outer join:
SELECT b.*
FROM InitialPolData b left outer join
MasterLockInsNew a on
b.id = a.id
where
a.id is null
Simple subquery will do.
select * from InitialPolData
where id not in (
select id from MasterLockInsNew
);
Try using NOT EXISTS:
SELECT Distinct i.*
FROM InitialPolData AS i
WHERE NOT EXISTS (SELECT 1
FROM MasterLockInsNew AS m
WHERE m.ID = i.ID)

ORACLE Not In on Multiple Columns

Kindly have a look at the following structure.
Table: A
+---------+----------+
| Col1A | Col2A |
+---------+----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 1 | 2 |
| 2 | 2 |
+---------+----------+
Table: B
+---------+----------+
| Col1B | Col2B |
+---------+----------+
| 2 | 1 |
| 3 | 1 |
+---------+----------+
Here is what I am trying to achieve that is to get the result as following:
Result
+---------+----------+
| Col1A | Col2A |
+---------+----------+
| 1 | 1 |
| 4 | 1 |
| 1 | 2 |
| 2 | 2 |
+---------+----------+
What I want :
I want to get the result of table A records which are not exists in Table B. It should be on the basis of both column. If the combination exist in first table then don't no show it.
What I have tried so far :
The first approach that I have tried was to use Not In statement. Following is my statement.
SELECT A.COL1A, A.COL2A
FROM A
WHERE A.COL1A NOT IN (
SELECT B.COL1B FROM B
);
But the issue with this approach didn't consider the second column. It will give me the following result.
+---------+----------+
| 1 | 1 |
| 4 | 1 |
+---------+----------+
While it will not show following as it should be sub-traced because of we didn't checked for other column.
+---------+----------+
| 1 | 2 |
| 2 | 2 |
+---------+----------+
Then I tried Not Exists but I didn't worked too. Here is my query.
SELECT A.COL1A, A.COL2A
FROM A
WHERE NOT EXISTS(
SELECT B.COL1B,B.COL2B FROM B
);
Edit
Sorry I forget to include the fiddle link.
Here it is : Fiddle Demo
For using Exists I think you should use it like this:
SELECT *
FROM A
WHERE
NOT EXISTS(SELECT 1
FROM B
WHERE A.Col1A = B.Col1B AND A.Col2A = B.Col2B)
One way to do this which is conceptually simple is to JOIN tables A and B on the two columns, and then SELECT only those rows in A which do not exist in B:
SELECT *
FROM A
LEFT OUTER JOIN B
ON (A.COL1A = B.COL1B AND A.COL2A = B.COL2B)
WHERE B.COL1B IS NULL
SELECT *
FROM a
WHERE (col1a, col2a) NOT IN (SELECT col1b, col2b FROM b);
But be aware that this will fail if either col1b or col2b contains NULL values.
SQLFiddle DEMO
SELECT A.COL1A, A.COL2A
FROM A
WHERE (Col1A, Col2A) NOT IN (
SELECT Col1B, Col2B FROM B
);
You can even use:
SELECT A.COL1A, A.COL2A
FROM A
WHERE (Col1A, Col2A) NOT IN (
(2, 1),
(3, 1)
);

Using SWITCH() to split data from a column into distinct columns, with associated data in reach row

I'm not quite sure how to properly phrase the question, but I am basically trying to develop an SQL query that SELECTs information from this table:
-------------------
| id | Val | Date |
|----|-----|------|
| 1 | A | 10/9 |
| 1 | B | 3/14 |
| 2 | A | 1/6 |
| 3 | A | 4/4 |
| 4 | B | 7/12 |
| 5 | A | 8/6 |
-------------------
And produces a table that looks like this:
------------------------------------------------
| id | Val_1 | Val_1_Date | Val_2 | Val_2_Date |
|----|-------|------------|-------|-------------
| 1 | A | 10/9 | B | 3/14 |
| 2 | A | 1/6 | | |
| 3 | A | 4/4 | | |
| 4 | | | B | 7/12 |
| 5 | A | 8/6 | | |
------------------------------------------------
I have already begun and developed the query to pull out the values in the Val fields into distinct columns:
SELECT * FROM
(
SELECT id, MAX(SWITCH( val='A', 'A')) as Val_1,
MAX(SWITCH( val='B', 'B')) as Val_2
FROM table1 GROUP BY id
)a
WHERE Val_1 IS NULL OR Val_2 IS NULL;
How would I expand on this to pull out their associated dates?
(I am using SWITCH() instead of CASE WHEN because I am using a driver similar to that of MS Access.)
Thanks!
I think following should work:
select id, SWITCH( val='A', 'A') as Val_1, SWITCH( val='A', Date) as Val_1_Date, SWITCH( val='B', 'B') as Val_2, SWITCH( val='B', Date) as Val_2_Date FROM table1 GROUP BY id
I do not prefer switches, so here is a query that does what you want without switches. This also answers your previous question.
Select distinct table1.ID, tableA.Val as Val_1, tableA.Date as Val_1_Date,
tableB.Val as Val_2, tableB.Date as Val_2_Date
FROM table1 left outer join
table1 as tableA on table1.id = tableA.id and tableA.Val = 'A' left outer join
table1 as tableB on table1.id = tableB.id and tableB.Val = 'B'
You can use ISNULL if that is preferred. This works because the first tables selects a distinct column of ID's, and the two joins get the A and B values. When creating selects using this method, make sure that you use tableA.Val = 'A' in the join conditions, and not in the where clause. Having tableA.Val = 'A' in the where clause will filter out all NULL's.

How to make select with extra columns that depends on existing ones

There goes example:
select * from table
and got
ID | NAME | MAIL | BOSS_ID |
1 | Mike | mike#mike.com | 2 |
2 | Josh | josh#hotmail.com | null |
What I actually want to do is make SELECT statement (somehow?) to show two more columns like:
ID | NAME | MAIL | BOSS_ID | BOSS_NAME | BOSS_MAIL
1 | Mike | mike#dfsfs.com | 2 | Josh | josh#dsa.com
2 | Josh | josh#dfsa.com | null | null | null
I know it looks silly, but that what I exactly have been asked to do...
All hints are much appreciatted!
You do an outer join to the table itself on ID and BOSS_ID.
SQL Fiddle
MS SQL Server 2012 Schema Setup:
create table YourTable
(
ID int,
Name varchar(10),
Mail varchar(20),
BOSS_ID int
)
insert into YourTable values
(1 , 'Mike' , 'mike#mike.com' , 2),
(2 , 'Josh' , 'josh#hotmail.com' , null)
Query 1:
select T1.ID,
T1.Name,
T1.Mail,
T2.Name as BossName,
T2.Mail as BossMail
from YourTable as T1
left outer join YourTable as T2
on T1.BOSS_ID = T2.ID
Results:
| ID | NAME | MAIL | BOSSNAME | BOSSMAIL |
|----|------|------------------|----------|------------------|
| 1 | Mike | mike#mike.com | Josh | josh#hotmail.com |
| 2 | Josh | josh#hotmail.com | (null) | (null) |
You cannot SELECT columns that do not exist. You will need to add them. You would want an ALTER TABLE statement like this:
ALTER TABLE yourtable ADD BOSS_NAME VARCHAR( 255 )