WHERE IN clause in temporary columns? - sql

I have a query that creates two temporary columns. Is there a way to check if column 2 value exists in column 1 value?
select x as column1, y as column 2
Result:
column 1 | column 2
x y
w x
how do I check if x exists in column 1 ? Ultimately I only want to get all the values in column 2 that do not have a matching value in column 1, Is this possible?

You can use EXCEPT for this:
Declare #testTable Table (col1 varchar(10), col2 varchar(10));
Insert Into #testTable (col1, col2)
Values ('x', 'y')
, ('w', 'x');
Select col2 From #testTable tt
Except
Select col1 From #testTable tt;

Related

Need to get the value from a column whose column name is based on a value in another table

Table A has columns ID, COL1, COL2, COL3.
Table B has columns AID, ColumnName.
I need to get the [ColumnName] value in Table A based on the value of [ColumnName] in Table B.
In the example below:
For ID 1, I need to get the value of column COL1 (This is the value of [ColumnName] for AID 1 in Table B).
For ID 2, I need to get the value of column COL3 (This is the value of [ColumnName] for AID 2 in Table B).
Table A
ID COL1 COL2 COL3
1 a aa aaa
2 b bb bbb
Table B
AID ColumnName
1 COL1
2 COL3
Desired Result:
ID VALUE
1 a
2 bbb
How can I do that ?
Thank you.
Unpivot then join
drop table t
go
drop table t1
go
create table t
(ID int, COL1 varchar(10), COL2 varchar(10), COL3 varchar(10))
go
create table t1
(AID int,ColumnName varchar(10));
go
insert into t values
(1 , 'a', 'aa', 'aaa'),
(2 , 'b', 'bb', 'bbb')
go
insert into t1 values
(1 , 'COL1'),
(2 , 'COL3')
go
with cte as
(select id, u.col, u.val
from t
unpivot
(
val
for col in (col1, col2, col3)
) u
)
select cte.id,cte.val
from cte
join t1 on
t1.aid = cte.id and
t1.columnname = cte.col
go
id val
----------- ----------
1 a
2 bbb
(2 row(s) affected)
One possible approach is to unpivot the columns in TableA using VALUES table value constructor and additional APPLY operator:
Tables:
SELECT *
INTO TableA
FROM (VALUES
(1, 'a', 'aa', 'aaa'),
(2, 'b', 'bb', 'bbb')
) v (ID, COL1, COL2, COL3)
SELECT *
INTO TableB
FROM (VALUES
(1, 'COL1'),
(2, 'COL3')
) v (AID, COL)
Statement:
SELECT b.AID, v.VALUE
FROM TableB b
JOIN TableA a ON b.AID = a.ID
CROSS APPLY (VALUES
('COL1', a.COL1),
('COL2', a.COL2),
('COL3', a.COL3)
) v (COL, [VALUE])
WHERE v.COL = b.COL
Result:
AID
VALUE
1
a
2
bbb

How to get records from one column such that there is no association with value in another column

I have the following MSSQL table:
Col1 Col2
A x
A y
A z
B x
B y
C x
C z
I want all the values from Col1 such that they have no record of association with a particular value of Col2
For example, I want value from Col1 such that 'z' does not occur for that value. The answer should be B
One another way:
select Col1
from your_table
group by Col1
having sum( case when Col2 = 'z' then 1 else 0 end ) = 0
You can make use of the lesser known EXCEPT keyword, like this :
SELECT Col1 FROM TableName
EXCEPT
SELECT Col1 FROM TableName WHERE col2 = 'z'
You can see this here -> http://rextester.com/KPZMB79095
Hope this helps!!!
There are a number of ways to do this. For me the clearest is to use EXCEPT:
SELECT Col1 FROM MyTable
EXCEPT
SELECT Col1 FROM MyTable WHERE Col2 = 'z';
Here we are clearly and simply saying that we want all the Col1 values, except those Col1 values that have a z entry. EXCEPT will automatically de-duplicate the result.
select distinct col1
from [table]
where col1 not in (
select col1 from [table] where col2 = 'z'
);
TRY THIS I think you want to retrieve the value where the given value does not exist in both the columns:
create table #sample(Col1 char(1), Col2 char(1))
insert into #sample values
('A', 'x'),
('A', 'y'),
('A', 'z'),
('B', 'x'),
('B', 'y'),
('C', 'x'),
('C', 'z')
declare #search char(1) = 'z'
select distinct col1
from #sample
where col1 not in (
select distinct Col1
from #sample
where (col1 = #search or col2 = #search))
OUTPUT:
col1
B

How to know the column name from a table based on the column values

I am working in Informix and I want to know if there is a simple way to know the tabname/colname by its possible column values.
For example:
table1
Register 1
==========
id 1
col1 3
col2 Y
Register 2
==========
id 2
col1 43
col2 X
Register 3
==========
id 2
col1 0
col2 Z
Register 4
==========
id 2
col1 23
col2 F
table2
Register 1
==========
id 1
col1 X
col2 Y
Register 2
==========
id 2
col1 X
col2 X
Register 3
==========
id 2
col1 Z
col2 Z
Register 4
==========
id 2
col1 X
col2 X
table3
Register 1
==========
id 1
col1 ASX
With this database, if I want to know the colnames and their related tabnames of the database that contain X, Y and Z (amoung other values).
It could be something like this:
select tabname, colname
where ('X','Y','Z') in colnamevalues --this has been invented by me
And this should return the following values:
table1.col2
table2.col1
table2.col2
--Note that the columns fetched contains also other values
--different from 'X', 'Y' and 'Z' but T didn't fix in this case
--the whole list of values, only some of them
I have queried for other Q&A but all of them look to use some functions of other databases such as Oracle or SQL Server and I don't understand them very well.
You can get all the tables that exist on a database by querying the systables:
SELECT tabname
FROM systables
WHERE tabtype = 'T' --get only tables
AND tabid > 99; --skip catalog tables
You can join it to the syscolumns table to get the columns:
SELECT t.tabname, c.colname
FROM systables t
INNER JOIN syscolumns c ON (c.tabid = t.tabid)
WHERE t.tabtype = 'T' AND t.tabid > 99;
And if you know the type of values you can even filter it. Example if you're looking for "strings":
SELECT t.tabname, c.colname
FROM systables t
INNER JOIN syscolumns c ON (c.tabid = t.tabid)
WHERE t.tabtype = 'T' AND t.tabid > 99
AND MOD(c.coltype,256) IN (
0, --CHAR
13, --VARCHAR
15, --NCHAR
16, --NVARCHAR
40, --LVARCHAR
43 --LVARCHAR
);
The next example works, but it really should be optimized and bullet proof, but can get you kick off.
When I have time I get another look at it and check what can be optimized and put some error handling.
Another way to do it is scripting, what OS are you running?
Schema creation:
CREATE TABLE tab1(
id INT,
col1 CHAR(3),
col2 CHAR(3)
);
INSERT INTO tab1 VALUES (1, 3, 'Y');
INSERT INTO tab1 VALUES (2, 43, 'X');
INSERT INTO tab1 VALUES (2, 0, 'Z');
INSERT INTO tab1 VALUES (2, 23, 'F');
CREATE TABLE tab2(
id INT,
col1 CHAR(3),
col2 CHAR(3)
);
INSERT INTO tab2 VALUES (1, 'X', 'Y');
INSERT INTO tab2 VALUES (2, 'X', 'X');
INSERT INTO tab2 VALUES (2, 'Z', 'Z');
INSERT INTO tab2 VALUES (2, 'X', 'X');
CREATE TABLE tab3(
id INT,
col1 CHAR(3)
);
INSERT INTO tab3 VALUES (1, 'ASX');
Sample function:
CREATE FUNCTION get_columns()
RETURNING LVARCHAR(257) AS col;
DEFINE stmt VARCHAR(255);
DEFINE tab_name VARCHAR(128,0);
DEFINE tab_id INTEGER;
DEFINE col_name VARCHAR(128,0);
DEFINE o_tname VARCHAR(128,0);
DEFINE o_cname VARCHAR(128,0);
CREATE TEMP TABLE out_table(
t_name VARCHAR(128,0),
c_name VARCHAR(128,0)
);
CREATE TEMP TABLE tab_v (
col1 VARCHAR(255)
);
INSERT INTO tab_v VALUES ('X');
INSERT INTO tab_v VALUES ('Y');
INSERT INTO tab_v VALUES ('Z');
FOREACH tables FOR
SELECT tabname, tabid
INTO tab_name, tab_id
FROM systables
WHERE tabid > 99 AND tabtype = 'T'
FOREACH column FOR
SELECT colname
INTO col_name
FROM syscolumns
WHERE tabid = tab_id
AND MOD(coltype,256) IN (
0, --CHAR
13, --VARCHAR
15, --NCHAR
16, --NVARCHAR
40, --LVARCHAR
43 --LVARCHAR
)
LET stmt = "INSERT INTO out_table "||
"SELECT '"||tab_name||"', '"||col_name||"' "||
"FROM "||tab_name||" "||
"WHERE EXISTS (SELECT 1 FROM tab_v v WHERE v.col1 = "||col_name||");";
EXECUTE IMMEDIATE stmt;
END FOREACH
END FOREACH
FOREACH out FOR
SELECT UNIQUE t_name, c_name
INTO o_tname, o_cname
FROM out_table
RETURN o_tname||"."||o_cname WITH RESUME;
END FOREACH
DROP TABLE out_table;
DROP TABLE tab_v;
END FUNCTION;
EXECUTE FUNCTION get_columns();

finding counts assigned to another field's value

Create table t1 (col1 (number), col2 (number), col3 (number);
Insert into t1 values (1,1,1);
Insert into t1 values (1,2,5);
Insert into t1 values (1,3,1);
Insert into t1 values (2,1,1);
Insert into t1 values (2,1,1);
Desired result
col1 col2
1 3
2 2
I need to return the value in col1 and the count of values found in col 2 for each distinct col1 value. Do not need col3
select col1, count(col1) from t1
group by col1

How to convert a column header and its value into row in sql?

I have a table with columns say col1, col2, col3. The table has many rows in it.
Let's assume val1, val2, val3 is one such row. I want to get the result as
Col1, Val1
Col2, Val2
Col3, Val3
That is 3 rows - one for each column and its value.
I am using SQL Server 2008. I read about pivots. Are pivots a way to solve this problem? Can someone route me to some examples or solutions how to solve this problem?
Thanks a lot
Maybe something like this:
Test data
DECLARE #T TABLE(Col1 INT, Col2 INT, Col3 INT)
INSERT INTO #T
VALUES (1,1,1)
Query
SELECT
*
FROM
(
SELECT
t.Col1,
t.Col2,
t.Col3
FROM
#T AS t
) AS SourceTable
UNPIVOT
(
Value FOR Col IN
(Col1,Col2,Col3)
) AS unpvt
Output
1 Col1
1 Col2
1 Col3
To do this kind of thing read the following: Using PIVOT and UNPIVOT
Pivot function allow you to convert row values in from of column..
Also check : Dynamic Pivoting in SQL Server
Example :
create table #temptable(colorname varchar(25),Hexa varchar(7),rgb varchar(1), rgbvalue tinyint)
GO
insert into #temptable values('Violet','#8B00FF','r',139);
insert into #temptable values('Violet','#8B00FF','g',0);
insert into #temptable values('Violet','#8B00FF','b',255);
insert into #temptable values('Indigo','#4B0082','r',75);
insert into #temptable values('Indigo','#4B0082','g',0);
insert into #temptable values('Indigo','#4B0082','b',130);
insert into #temptable values('Blue','#0000FF','r',0);
insert into #temptable values('Blue','#0000FF','g',0);
insert into #temptable values('Blue','#0000FF','b',255);
SELECT colorname,hexa,[r], [g], [b]
FROM
(SELECT colorname,hexa,rgb,rgbvalue
FROM #temptable) AS TableToBePivoted
PIVOT
(
sum(rgbvalue)
FOR rgb IN ([r], [g], [b])
) AS PivotedTable;
Create a temproary table:
CREATE TABLE #table2
(
name NCHAR,
bonus INT
)
Now Select and execute the below statement if there is an empty.
SELECT * FROM #table2
INSERT INTO #table2 (name,bonus) VALUES ('A',10)
INSERT INTO #table2 (name,bonus) VALUES ('B',20)
INSERT INTO #table2 (name,bonus) VALUES ('C',30)
After insert the values into table. select and execute the below line if you get records:
SELECT * FROM #table2
Input:
name bonus
A 10
B 20
C 30
Change the input into like this result
Result:
Cost A B C
Bonus 10 20 30
By using this code:
SELECT 'Bonus' AS Cost,
[A],[B],[C]
FROM
(SELECT name, Bonus
FROM #table2) AS TempTbl
PIVOT
(
AVG(bonus)
FOR [name] IN ([A],[B],[C])
) AS PivotTable;