write a query in sql - sql-server-2005

I have two tables that have following rows:
Table1
ID Name Number
=====================
1 a 100
2 b 200
3 c 300
Table2
ID Number Check
=====================
1 100 0
2 200 1
3 300 null
Now I want the following table:
table
---------------------
Name Number check
=====================
a 100 0
c 300 null
What query I must to write.
*You notice that the column of check in the row of 'c' in final table is null.
Thanks.

Left outer join is your friend:
select table1.name, table1.nmber, table2.check from table1 left outer join table2 on table1.nmber = table2.number

Assuming that the nmber column in table1 = number column in table2
SELECT a.name, a.nmber, b.check
FROM table1 a JOIN table2 b ON a.nmber = b.number

I believe your looking for
select a.Name, a.Nmber, b.Check
from Table1 a join table2 b
on a.Nmber = b.Number
can also add a where clase e.g.
where a.Name is not b
where b.check is not 1
etc
Hard to tell from your question how you want your results to exclude b

Set up test data.
create table table1(ID int, Name char(1), Number int)
create table table2(ID int, Number int, [Check] int)
insert into table1 values (1, 'a', 100)
insert into table1 values (2, 'b', 200)
insert into table1 values (3, 'c', 300)
insert into table2 values (1, 100, 0)
insert into table2 values (2, 200, 1)
insert into table2 values (3, 300, null)
The query
select
table1.Name,
table1.Number,
table2.[Check]
from table1
inner join table2
on table1.ID = table2.ID
where Name <> 'b'
Result
a 100 0
c 300 NULL
You must use square brackets around column name [check] because check is a reserved word. in SQL Server.

This question has been edited a lot. I believe that the answer to the original question differ from the answer to the current question.
Here is the setup for version 1 one of the question.
create table table1(ID int, Name char(1), Number int)
create table table2(ID int, Number int, [Check] int)
insert into table1 values (1, 'a', 100)
insert into table1 values (2, 'b', 200)
insert into table1 values (3, 'c', 300)
insert into table2 values (1, 100, 0)
insert into table2 values (2, 200, 1)
To get c from table1 when joined to table2 you need to use a left outer join.
select
table1.Name,
table1.Number,
table2.[Check]
from table1
left outer join table2
on table1.ID = table2.ID
where table1.Name <> 'b'
Even in this version you need the square brackets around check.

Related

Oracle - Compare two sets of columns are equal

I have an output of a table of a single column with values similar to
OUTPUT
A
B.
And I have a table with a set consisting of an ID and values
ID
Data
1
A
1
B
1
C
2
A
2
B
3
B
3
C
3
D
I'm having trouble to build an oracle query that compares the output of the first table with the data column of the second table, and let me know which id matches the exact same data if I were to group them by id.
So for this scenario only ID 2 should be returned since it matches exactly, but ID 1 won't return because it has an extra value
Left join TableA to TableB.
Then the 100% match will have no unmatched OUTPUT.
And the matched will have the same count as what's in TableA.
SELECT b.ID
FROM TableB b
LEFT JOIN TableA a ON a.OUTPUT = b.Data
GROUP BY b.ID
HAVING COUNT(CASE WHEN a.OUTPUT IS NULL THEN 1 END) = 0
AND COUNT(DISTINCT a.OUTPUT) = (SELECT COUNT(*) FROM TableA)
ORDER BY b.ID;
ID
2
Demo on db<>fiddle here
The first select in the with clause is a join of tables.
The second select uses the first select and finds the id whose column "Data" takes all the values from the output column of table A.
The third select contains only the ids without the "Data" in table A.
The result contains only ids that have all outputs and no extra.
Unique values in both tables are prerequisites.
Oracle 11RG2.
DDL:
CREATE TABLE TableA
("OUTPUT" varchar2(1))
;
INSERT ALL
INTO TableA ("OUTPUT")
VALUES ('A')
INTO TableA ("OUTPUT")
VALUES ('B')
SELECT * FROM dual
;
CREATE TABLE TableB
("ID" int, "Data" varchar2(1))
;
INSERT ALL
INTO TableB ("ID", "Data")
VALUES (1, 'A')
INTO TableB ("ID", "Data")
VALUES (1, 'B')
INTO TableB ("ID", "Data")
VALUES (1, 'C')
INTO TableB ("ID", "Data")
VALUES (2, 'A')
INTO TableB ("ID", "Data")
VALUES (2, 'B')
INTO TableB ("ID", "Data")
VALUES (3, 'B')
INTO TableB ("ID", "Data")
VALUES (3, 'C')
INTO TableB ("ID", "Data")
VALUES (3, 'D')
SELECT * FROM dual
;
SQL:
with a (id, "Data", output) as (
select
id, "Data", output
from
tableb left join tablea on "Data"=output
)
select
id
from
a
where
output is not null
group by id
having count("Data") = (select count(output) from tablea)
minus
select id from a where output is null
;
Output:
ID
2

SQL - Multiple Inner Join, most recent

I am wondering why the below SQL query does not work properly. I am attempting to return the fields from table 1 and table 2 based on the most recent date AND only those elements in those tables that have the name Steve from a third table.
This query, meanwhile, does not actually limit the results to those with the name of Steve. If I remove the second Inner Join and focus on fields only in Table 1 to limit the universe, it works fine.
Appreciate your help on this. I am using Microsft SQL Server Management Studio.
Select *
From [db].table1
INNER JOIN [db].table2 ON table1.id=table2.id
INNER JOIN [db].table3 ON table1.id=table3.id
WHERE (table1.AsOfDate=(SELECT MAX(AsOfDate) from [db].table1))
and table3.Name = 'Steve'
The ID's may not be referring to the same ID across all three tables. Your joins assumes that is the case though. I mirrored your query with sample temp tables and your query works.
--SAMPLE TABLES
IF object_id('tempdb..#table1') is not null drop table #table1
if object_id('tempdb..#table2') is not null drop table #table2
if object_id('tempdb..#table3') is not null drop table #table3
CREATE TABLE #table1 (id INT, my_date date)
INSERT INTO #table1 (id, my_date) VALUES
(1, '1/1/2018'),
(2, '1/2/2018'),
(3, '1/1/2018')
CREATE TABLE #table2 (id INT, some_field VARCHAR(10))
INSERT INTO #table2 (id, some_field) VALUES
(1, 'abc'),
(2, 'xyz'),
(3, 'foo')
CREATE TABLE #table3 (id INT, name VARCHAR(10))
INSERT INTO #table3 (id, name) VALUES
(1, 'jon'),
(2, 'steve'),
(3, 'jane')
--QUERY
SELECT *
FROM #table1 AS x
INNER JOIN
#table2 AS y ON x.id=y.id
INNER JOIN
#table3 AS z ON z.id=x.id
WHERE x.my_date=(SELECT MAX(my_date) from #table1)
and z.name = 'Steve'
output
id my_date id some_field id name
2 2018-01-02 2 xyz 2 steve
I think the simplest way is a window function in the order by:
Select top (1) with ties . . . -- list the columns explicitly
from [db].table1 t1 join
[db].table2 t2
on t1.id = t2.id join
[db].table3 t3
on t1.id = t3.id
where t3.Name = 'Steve'
order by rank() over (order by t1.AsOfDate);

Update table value by adding from other table

Can you please help me out with the below issue?
I have a table like below.
Table-1
Sales_RepID-- Name-- Products_Count
1-- ABC-- 2
2-- XYZ-- 4
3-- XXX-- 3
Table-2
Order_ID-- Sales_RepID-- Products_Count
1001-- 2 -- 2
1002-- 1 -- 1
1003-- 2 -- 1
1004-- 3 -- 3
1005-- 2 -- 2
Table - 1 Result
Sales_RepID, --Name, --Products_Count
1-- ABC --3
2-- XYZ --9
3-- XXX --6
I want to add table-2 Products_Count to Table-1 Products_Count for each Sale_RepID in the table-1
Can you please help with SQL Query?
My database is MS SQL SERVER
For MS SQL Server, please try:
UPDATE T
SET T.Products_Count=T.Products_Count+x.VSum
FROM Table1 T JOIN
(
SELECT DISTINCT
Sales_RepID,
SUM(Products_Count) OVER (PARTITION BY Sales_RepID) VSum
FROM
Table2
)x ON T.Sales_RepID=x.Sales_RepID
create table table1(sales_repId int,name varchar(10),product_count int);
create table table2(order_id int,sales_repId int,product_count int);
insert into table1 values(1,'ABC',2);
insert into table1 values(2,'XYZ',4);
insert into table1 values(3,'XXX',3);
insert into table2 values(1001,2,2);
insert into table2 values(1002,1,1);
insert into table2 values(1003,2,1);
insert into table2 values(1004,3,3);
insert into table2 values(1005,2,2);
select a.sales_repid,name,a.product_count+sum(b.product_count)
from table1 a
inner join table2 b
on a.sales_repid=b.sales_repid
group by a.sales_repid,name,a.product_count
order by a.sales_repid
UPDATE
update table1
set product_count = netProduct
from (
select a.sales_repid,name,a.product_count+sum(b.product_count) as netProduct
from table1 a
inner join table2 b
on a.sales_repid=b.sales_repid
group by a.sales_repid,name,a.product_count
) z
inner join table1 x
on z.sales_repid=x.sales_repid
TRY THIS
DECLARE #TABLE1 AS TABLE( Sales_RepID INT,Name VARCHAR(100), Products_Count int)
DECLARE #TABLE2 AS TABLE( Order_ID INT,Sales_RepID INT, Products_Count int)
INSERT INTO #TABLE1
VALUES(1,'ABC',2),(2,'XYZ',4),(3,'XXX',3)
INSERT INTO #TABLE2
VALUES(1001,2,2),(1002,1,1),(1003,2,1),(1004,3,3),(1005,2,2)
SELECT * FROM #TABLE1
SELECT * FROM #TABLE2
UPDATE T1
SET T1.Products_Count = T1.Products_count + total
FROM #TABLE1 T1
CROSS APPLY (
SELECT total= sum(Products_count)
FROM #Table2 T2
WHERE T1.Sales_RepID =t2.Sales_RepID ) Z
To output as a select:
select
t1.Sales_RepID,
t1.Name,
t1.Products_Count + sum(t2.Products_Count)
from table1 t1
left join table2 t2 on t2.Sales_RepID = t1.Sales_RepID
To update the total in table1, adding the total from table2:
update table1 set
Products_Count = Products_Count + (
select sum(Products_Count)
from table2
where Sales_RepID = table1.Sales_RepID)
These queries will work in all SQL dialects.
MS SQL Server has a special syntax for updating using a join, which will perform much better than the universal update syntax above:
update t1 set
t1.Products_Count = t1.Products_Count + t2.Products_Count
from table1 t1
join (select Sales_RepID, sum(Products_Count) Products_Count
from table2
group by Sales_RepID) t2
on t2.Sales_RepID = t1.Sales_RepID;
See a live demo of this update statement executing on SQLFiddle.
Note that this is an unusual query. Typically, such denormalized values are not cumulative: they are a determinable calculated value, which in this case wold be simply the sum, not the existing value plus the sum. Your design means that the query can only be executed once. After than you'll be repeatedly re-adding the total from table2.
Consider redesigning your tables to have the straight sum from table2 in table1, ie:
update t1 set
t1.Products_Count = t2.Products_Count
from table1 t1
join (select Sales_RepID, sum(Products_Count) Products_Count
from table2
group by Sales_RepID) t2
on t2.Sales_RepID = t1.Sales_RepID;

2 different condition on one SQL query

I have 2 tables. I need to pick some ids from table one and based one condition and insert into table 2. The second column again must come from tableA but based on a different condition
Table A
NC 1
NC 2
SC 3
SC 4
Table B
1 100
1 200
2 100
2 200
I want to insert rows to table B so it would look like this....
1 100
1 200
2 100
2 200
3 100
3 200
4 100
4 200
I am picking 3 and 4 from table A based on the state condtion = 'SC'and now I want to know how to pick the values of 100 and 200 which NC has...
Sorry if I havent worded it correctly
-- sample data
create table tbla (code char(2), id int);
insert into tbla values ('NC', 1);
insert into tbla values ('NC', 2);
insert into tbla values ('SC', 3);
insert into tbla values ('SC', 4);
create table tblb (id int, value int);
insert into tblb values (1, 100);
insert into tblb values (1, 200);
insert into tblb values (2, 100);
insert into tblb values (2, 200);
-- your query to INSERT the new rows into tblb
insert into tblb
select x.id, y.value
from
(
select distinct a.id
from tbla a
where a.code = 'SC'
) x
cross join
(
select distinct b.value
from tbla a
join tblb b on a.id = b.id
where a.code = 'NC'
) y
left join tblb b on b.id = x.id and b.value = y.value
where b.id is null;
You can do it by a query like :
Select a.id, b.value
from "Table A" a
join "Table B" b
on b.id=1 --This condition pick the two first rows on table B.
where a.condtion = 'SC'
This is not a elegant solution, but it work.

Generic SQL questions

I have a table A
ID Term
10 A
10 B
10 C
20 A
20 B
20 E
what's the best way to write a sql to
get ID 10, if I try to find (A,B,C)
get NOTHING if I try to find (A,B)
get ID 20, if I try to find NOT in (C,D)
.
Select distinct ID from TableA where Term in (A,B,C) will return both 10 and 20
Select distinct ID from TableA where Term in (A,B) will also return both 10 and 20
Select distinct ID from TableA where Term NOT in (C,D) will also return both 10 and 20
Thanks!
1.
SELECT ID
FROM TableA
WHERE Term IN ('A','B','C')
GROUP BY ID
HAVING COUNT(ID)=3
LIMIT 1
Here 3 would be the length of the set (A,B,C in this case). 2 & 3 could probably be some variation of the above.
I assume you want one form of query that can be used to answer all three questions, not a different kind of query for each question.
These solutions take advantage of COUNT() not counting NULLs. When the OUTER JOIN does not match a row in t2, it results in NULL for all columns from t2.
get ID 10, if I try to find (A,B,C)
ID 10 has three distinct term values, and we're searching for all three.
SELECT t1.ID
FROM TableA t1 LEFT OUTER JOIN TableA t2
ON (t1.ID = t2.ID AND t1.term = t2.term AND t2.term IN ('A', 'B', 'C'))
GROUP BY t1.ID
HAVING COUNT(t1.term) = COUNT(t2.term);
get NOTHING if I try to find (A,B)
Both ID 10 and ID 20 have three distinct term values, but our search is only for two. The counts are 3 = 2 for both IDs, so neither have equal counts.
SELECT t1.ID
FROM TableA t1 LEFT OUTER JOIN TableA t2
ON (t1.ID = t2.ID AND t1.term = t2.term AND t2.term IN ('A', 'B'))
GROUP BY t1.ID
HAVING COUNT(t1.term) = COUNT(t2.term);
get ID 20, if I try to find NOT in (C,D)
ID 20 has three distinct term values, and all three of them are NOT 'C' or 'D'. So the counts are equal.
SELECT t1.ID
FROM TableA t1 LEFT OUTER JOIN TableA t2
ON (t1.ID = t2.ID AND t1.term = t2.term AND t2.term NOT IN ('C', 'D'))
GROUP BY t1.ID
HAVING COUNT(t1.term) = COUNT(t2.term);
Q1
SQLite version 3.6.10
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> create table A(ID smallint, term varchar(1));
sqlite> insert into A values(10, 'A');
sqlite> insert into A values(10, 'B');
sqlite> insert into A values(10, 'C');
sqlite> insert into A values(20, 'A');
sqlite> insert into A values(20, 'B');
sqlite> insert into A values(20, 'E');
sqlite> SELECT ID FROM A WHERE TERM = 'A' INTERSECT SELECT ID FROM A WHERE TERM
= 'B' INTERSECT SELECT ID FROM A WHERE TERM = 'C';
10
Q2
sqlite> SELECT ID FROM A WHERE TERM = 'A' EXCEPT SELECT ID FROM A WHERE TERM = '
B';
returns no results. EXCEPT can also be called MINUS in some versions of SQL
Q3
sqlite> SELECT ID FROM A EXCEPT SELECT ID FROM A WHERE TERM = 'C' UNION SELECT I
D FROM A WHERE TERM = 'D';
20
CREATE TABLE mySearch (
search_id INT,
val CHAR(1),
is_required INT,
is_excluded INT
)
INSERT INTO mySearch VALUES (1, 'A', 1, 0) -- Search1 : A is required
INSERT INTO mySearch VALUES (1, 'B', 1, 0) -- Search1 : B is required
INSERT INTO mySearch VALUES (1, 'C', 1, 0) -- Search1 : C is required
INSERT INTO mySearch VALUES (2, 'A', 1, 0) -- Search2 : A is required
INSERT INTO mySearch VALUES (2, 'B', 1, 0) -- Search2 : B is required
INSERT INTO mySearch VALUES (3, 'C', 0, 1) -- Search3 : C is excluded
INSERT INTO mySearch VALUES (3, 'D', 0, 1) -- Search3 : D is excluded
SELECT
[search].search_id,
[data].id
FROM
TableA AS [data]
LEFT JOIN
my_search AS [search]
ON [search].val = [data].Term
GROUP BY
[search].search_id,
[data].ID
HAVING
ISNULL(SUM([search].is_included),0) = (SELECT SUM(is_included) FROM mySearch WHERE search_id = [search].search_id)
AND MAX([search].is_excluded) IS NULL
Should satisfy all three seaches in one query. Unfortunately I can't test it as I'm at the in-laws house and they don't have geek toys to test on ;)