How to form an SQL query that is like using 'IN' across two columns as pairs? - sql

I have two integer columns and I wish to select rows with particular pairings of values. What SQL syntax can I use? For example, using IN it might look something like this if IN supported this syntax:
select *
from myTable
where value1, value2 in ((2,3), (3,4), (2,5), (3,6))
To select those rows with
value1 == 2 and value2 == 3 or value1==3 and value2==4 or 2/5 or 3/6.
I'm using a proprietary SQL system, so basic SQL is preferred. Or if there is none, having a statement that works in some standard SQL would be useful as well.

select yourtable.*
from yourtable
inner join
(
select 2 as v1, 3 as v2
union select 3,4
union select 2,5
union select 3,6
) pairs
on yourtable.value1 = pairs.v1
and yourtable.value2 = pairs.v2

Well in SQL Server you can't use IN that way unfortunately. I think your best bet is going to be to write it out like you did below your code sample or to load your data into a CTE or something and then joining on that.

same can be achieved by using VALUES
select table_name.*
from table_name tn,
(values(2,3), (3,4), (2,5), (3,6) ) as val(v1,v2)
where tn.value1 = val.v1 and tn.value2 = val.v2

Related

Transposing Column Data into Row Data SQL

I have some data that looks like this in an SQL table.
[ID],[SettleDate],[Curr1],[Curr2][Quantity1],[Quantity2],[CashAmount1],[CashAmount2]
The issue i have, i need to create 2 records from this data (all information from 1 and all information of 2). Example below.
[ID],[SettleDate],[Curr1],[Quantity1],[CashAmount1]
[ID],[SettleDate],[Curr2],[Quantity2],[CashAmount2]
Does anyone have an ideas how to do so?
Thanks
A standard (ie cross-RDBMS) solution for this is to use union:
select ID, SettleDate, Curr1, Quantity1, CashAmount1 from mytable
union all select ID, SettleDate, Curr2, Quantity2, CashAmount2 from mytable
Depending on your RBDMS, neater solutions might be available.
Just another option. The ItemNbr 1/2 is just to maintain which element.
Select A.[ID]
,A.[SettleDate]
,B.*
From YourTable A
Cross Apply ( values (1,[Curr1],[Quantity1],[CashAmount1])
,(2,[Curr2],[Quantity2],[CashAmount2])
) B{ItemNbr,Curr,Quantity,CashAmount)

SQL Logic: Finding Non-Duplicates with Similar Rows

I'll do my best to summarize what I am having trouble with. I never used much SQL until recently.
Currently I am using SQL Server 2012 at work and have been tasked with trying to find oddities in SQL tables. Specifically, the tables contain similar information regarding servers. Kind of meta, I know. So they each share a column called "DB_NAME". After that, there are no similar columns. So I need to compare Table A and Table B and produce a list of records (servers) where a server is NOT listed in BOTH Table A and B. Additionally, this query is being ran against an exception list. I'm not 100% sure of the logic to best handle this. And while I would love to get something "extremely efficient", I am more-so looking at something that just plain works at the time being.
SELECT *
FROM (SELECT
UPPER(ta.DB_NAME) AS [DB_Name]
FROM
[CMS].[dbo].[TABLE_A] AS ta
UNION
SELECT
UPPER(tb.DB_NAME) AS [DB_Name]
FROM
[CMS].[dbo].[TABLE_B] as tb
) AS SQLresults
WHERE NOT EXISTS (
SELECT *
FROM
[CMS].[dbo].[TABLE_C_EXCEPTIONS] as tc
WHERE
SQLresults.[DB_Name] = tc.DB_NAME)
ORDER BY SQLresults.[DB_Name]
One method uses union all and aggregation:
select ab.*
from ((select upper(name) as name, 'A' as which
from CMS.dbo.TABLE_A
) union all
(select upper(name), 'B' as which
from CMS.dbo.TABLE_B
)
) ab
where not exists (select 1
from CMS.dbo.TABLE_C_EXCEPTION e
where upper(e.name) = ab.name
)
having count(distinct which) <> 2;
SQL Server is case-insensitive by default. I left the upper()s in the query in case your installation is case sensitive.
Here is another option using EXCEPT. I added a group by in each half of the union because it was not clear in your original post if DB_NAME is unique in your tables.
select DatabaseName
from
(
SELECT UPPER(ta.DB_NAME) AS DatabaseName
FROM [CMS].[dbo].[TABLE_A] AS ta
GROUP BY UPPER(ta.DB_NAME)
UNION ALL
SELECT UPPER(tb.DB_NAME) AS DatabaseName
FROM [CMS].[dbo].[TABLE_B] as tb
GROUP BY UPPER(tb.DB_NAME)
) x
group by DatabaseName
having count(*) < 2
EXCEPT
(
select DN_Name
from CMS.dbo.TABLE_C_EXCEPTION
)

Sum Distinct By Other Column

I have a problem with PL/SQL since i am new in PL/SQL world.
Let's say i have table like this.
COlumnA COlumnB COlumnC
1 5000000000 X
1 5000000000 X
2 4350000000 X
2 4350000000 X
3 10000000000 X
3 10000000000 X
3 10000000000 X
4 1809469720 Y
5 10000000000 X
5 10000000000 X
6 3000000000 X
6 3000000000 X
And i want to produce select statement as below.
ColumnC |Sum
X |32350000000
Y |1809469720
I have solved this problem in Oracle 12c with inner query, but when the system need to go to Oracle 11g, my query doesn't work anymore, i need to have the expected result with only one select statement.
Could anyone please advise?
Thank you!
This is what I came up with... using an inline view rather than a correlated subquery in the SELECT list.
SELECT d.columnc AS "ColumnC"
, SUM(d.columnb) AS "Sum"
FROM ( SELECT t.columna
, t.columnb
, t.columnc
FROM tablea t
GROUP
BY t.columna
, t.columnb
, t.columnc
) d
GROUP
BY d.columnc
This uses an inline view (aliased as "d") to return a "distinct" set of rows from tablea. We can get a distinct set, using a GROUP BY clause, or including the DISTINCT keyword, or even by writing a query that uses a UNION set operator.
Just wrap that query in parens, assign an alias, and use it in the FROM clause, as if it were a table or view.
The statement operates similarly to referencing a VIEW in the FROM clause.
You don't need to do this, but to illustrate how the query above operates. We could create a view, like this:
CREATE VIEW d AS
SELECT t.columna
, t.columnb
, t.columnc
FROM tablea t
GROUP
BY t.columna
, t.columnb
, t.columnc
And then we can reference the view in the FROM clause of another query, for example
SELECT d.columnc AS "ColumnC"
, SUM(d.columnb) AS "Sum"
FROM d
GROUP
BY d.columnc
But we don't actually need to create the VIEW object. We can include the view query as an "inline view".
I don't believe that Oracle 11g has a restriction on the nesting of inline views to three levels. I suspect that the restriction you are running into is related to correlated subqueries. The subquery can reference columns from the outer query, but only up one level... columns from the query it's used in. It can't reference columns in a query that is further out. (I've not confirmed with testing, but that's my recollection.)
This is where the actual ORA- and/or PLS- error message from Oracle would be of some help in identifying the restriction you are running into.
First find the distinct values of COlumnA,COlumnB and COlumnC then do the aggregation
Try this
select COlumnC,sum(COlumnB) from
(
select distinct COlumnA,COlumnB,COlumnC
from Table1
)
Group by COlumnC
Or you can simple use this query.
Select sum(columnB) as sum,columnC from table_name group by ColumnC;

SQL "WITH" to include multiple derived tables

Can I write something like below. But this is not giving proper output in WinSQL/Teradata
with
a (x) as ( select 1 ),
b (y) as ( select * from a )
select * from b
Do you really need to use CTEs for this particular solution when derived tables would work as well:
SELECT B.*
FROM (SELECT A.*
FROM (SELECT 1 AS Col1) A
) B;
That being said, I believe multiple CTEs are available in Teradata 14.10 or 15. I believe support for a single CTE and the WITH clause were introduced in Teradata 12 or 13.
You call the dependent 1st and then the parent
like this and it will work. Why is it like that ? Teradata likes people to play with it longer and spend more time with it, making it feel important
with
"b" (y) as ( select * from "a" ),
"a" (x) as ( select '1' )
select * from b

Subquery without temporary tables

I'm having a problem which I wanted to solve with temporary tables, however, I discovered this is not really a good approach in Oracle.
I issue a select command from multiple tables and get Result1. I then want to combine columns 2,3 into 1 column which contains the unique values from columns 2,3 e.g.
Select distinct(col2) from Result1
UNION
Select distinct(col3) from Result1
As Result2
I then want to use the values from Result2 in a subquery. An easy way to do this last part to make the query above part of my Where clause as a subquery, but again I don't know how to reference Result1. So what I want is:
Select * from xyz where col in
(Select distinct(col2) from Result1
UNION
Select distinct(col3) from Result1)
What is the best way to combine the results of these queries in Oracle without a temp table?
First, your query can be written as:
Select *
from xyz
where col in (Select col2 from Result1 union all
Select col3 from Result1
)
The in automatically handles duplicates in this case. This is better written as the following, using with for result1:
with result1 as (
<your query here>
)
select *
from xyz
where exists (select 1 from result1 r where xyz.col1 = r.col2 or xyz.col1 = r.col3);
Does that solve your problem?