Subtracting two SELECT statements to produce a single result? - sql

I did find this post: how do I subtract values from two select statements
but I cannot get it to work on SQL-Server 2008.
I have two basic SELECT statements. No GROUP BYs or anything, just a SELECT, FROM and WHERE.
I would like to subtract one of these SELECTs from the other. Both return one row and column.
Could somebody please help?
SELECT
((SELECT Field1 AS BaseBase FROM Table1
WHERE Field2 = 'something'
AND Field3 =
(SELECT Field4 FROM SEL_Function('something','something')) as tab1)
-
((SELECT Field5 FROM SEL_Function('something','something') as tab2)

Alright I don't think the cross apply is necessary fiddle won't allow functions but check out this fiddle. You will want to swap out the table of the same name with the function. I think you were getting bit by a combination of alias and paren mismatches.
http://sqlfiddle.com/#!3/dc72f/13

In the provided link there is
select v1.Value1 - v2.Value2 from ((bla) AS v1 CROSS JOIN (blubb) AS v2
which I would translate to this (in your case)
SELECT tab1.BaseBase - tab2.Minus FROM
((SELECT Field1 AS BaseBase FROM Table1
WHERE Field2 = 'something'
AND Field3 =
(SELECT Field4 FROM SEL_Function('something','something')) as tab1
CROSS JOIN
(SELECT Field5 AS Minus FROM SEL_Function('something','something')) as tab2)
Like stated in the comments, it would be advisable to specify the affected table. However, I think that it might work (I have no testing system at hand :( ) without those explicit definitions as well, because the names are unique.

Related

Subquery with 2 parameters in SQL

I have a table in SQL which looks like this:
[
Now, I want the resultant table based on 2 conditions:
Prev_trans_id should match the transactions_ID
Only those entries should come where mod of Amount value is not equal.
The resultant table should like this:
SO, in the resultant table, I dont want row with Transcation_ID as 104 since the mod of amount is same. $1 was paid and $1 was refunded.
I was able to do 1st part of it but not able to do 2nd part as I am new to SQL. This is my code for the 1st part:
select * from sample_table
where prev_trans_id in
(select transaction_id from sample_table)
If I can get the 2nd condition also incorporated in the same query, it would be very helpful.
Use a JOIN, not IN
SELECT t1.*
FROM sample_table AS t1
JOIN sample_table AS t2
ON t1.prev_trans_id = t2.transaction_id AND t1.amount != -1 * t2.amount
BTW, it's not mod of the amounts, it's the negation of the amounts that you want to compare.
There's no need to use a subquery here as it can be achieved with a basic select ... from ... where ... query on table1 and table2. Please see the query below:
select table2.*
from sample_table table1, sample_table table2
where table1.transaction_id = table2.prev_trans_id
and (table1.amount - table2.amount) <> 0

Dynamic Script for Column Comparison between two table in sql server

I have two tables with 28 columns in them. In the production environment, SQL Server collation is set as case sensitivity.
I have to check the value like as:
UPPER(Target.SKU) <> UPPER(Source.SKU)
OR UPPER(Target.PRC) <> UPPER(Source.PRC)
OR UPPER(Target.PACKSIZE) <> UPPER(Source.PACKSIZE).
Is it possible to do it dynamically, without repeating the UPPER statement
for each column?
I am just trying to do it more neatly. Please share your thoughts.
Thanks
I would do two things:
First, before going through line by line, check if the both tables have the same content
SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM target_table
SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM source_table
If these numbers match, you have a very, very high probability the content of both tables is identical.
If the numbers don't match, check row by row to find the different records:
;with cte1 AS (
SELECT t.id, BINARY_CHECKSUM(*) AS checker
FROM target_table t
)
;with cte2 AS (
SELECT s.id, BINARY_CHECKSUM(*) AS checker
FROM source_table s
)
SELECT cte1.id, cte2.id
FROM cte1
INNER JOIN cte2
ON cte1.id = cte2.id
AND cte1.checker <> cte2.checker
This should return the specific records in your table that do not match in both tables.
If you have other logic in your statement you could do a sub select with that logic first and select the fields as UPPER then do the comparrison
select fields
FROM (
Select UPPER(SKU), UPPER(PRC), UPPER(PACKETSIZE), otherfields
from table
where logic
)
WHERE Target. SKU <> Source. SKU
OR Target. PRC <> Source. PRC
OR Target. PACKSIZE <> Source. PACKSIZE

Query who will output ONLY numbers in field1 who exceeded a specific threshold

I have to make a "simple" query on ORACLE DB who will output ONLY numbers in field1 who exceeded a specific threshold.
In other words, assuming I have the following data in database.
FIELD1 FIELD2
========= ==============
3291234567 333991123456789
3277654321 333011123456789
3481234567 333101123456789
3291234567 333991123456789
3291234567 333011123456789
3277654321 333015123456789
3277654321 333103123456789
3277654321 333201123456789
3481234567 333112123456789
I want to output only number in field1 with occurrences >= 3, so the query output will be:
FIELD1 FIELD2
========= ==============
3277654321 333011123456789
3277654321 333015123456789
3277654321 333103123456789
3277654321 333201123456789
3291234567 333991123456789
3291234567 333991123456789
3291234567 333011123456789
Please help!!!!
Thanks
Lucas
This should work for you (using COUNT(*) as a window function) - I assume you want Oracle even though the question is tagged mysql:
SELECT field1, field2 FROM (
SELECT field1, field2, COUNT(*) OVER ( PARTITION BY field1 ) field1_cnt
FROM mytable
) WHERE field1_cnt >= 3;
Accomplishing this in MySQL is a bit trickier since MySQL doesn't have window functions.
SELECT * FROM db_table WHERE field1 IN
( SELECT field1 FROM db_table GROUP BY field1 HAVING count(*) >= 3 )
I believe this will work in Oracle and MySQL. Using a subquery, you list all the field1 entries that have three occurrences, then the original query is run to match field1 entries in that list.
UPDATE
Referring to additional information from your comments:
Since subquery in this very case is a set of grouped information serving for identification which FIELD1 values satisfy the condition of having more than 3 occurences in yourtable and because of the fact that this additional info is INNER JOIN-ed to yourtable, it should be enough if you added field filtering with WHERE clause in the top-most query.
So the query with WHERE clause should look like:
SELECT A.FIELD1, A.FIELD2
FROM
yourtable A
INNER JOIN
(
SELECT FIELD1, COUNT (1)
FROM yourtable
GROUP BY FIELD1
HAVING COUNT (1) >= 3
) B
ON A.FIELD1 = B.FIELD1
WHERE
A.FIELD1 = 'some_value'
Again, by your last comment, if you have more fields in yourtable that you need to filter by, you may add them like:
..................
WHERE
A.FIELD1 = 'some_value'
AND A.FIELD5 = 'some_field5_val'
AND (...)

How could I get consecutive pairs in a column with duplication?

I'm struggling to find a way to get consecutive pairs in a column of a table but failed so far. To explain more specifically, let me give an example.
Let's say I have a table (t1) with 1 column (col1) of char as follows:
col1
------
a
a
a
c
e
a
g
i
What I want to get is consecutive pairs like
(a,a) (a,a) (a,c) (c,e) (e,a) (a g) (g,i).
For example, building a new table(t2) which has a column(col2) of string as follows:
col2
------
a,a
a,a
a,c
c,e
e,a
a,g
g,i
(if I can exclude the pairs of same value (e.g. (a,a)), it would be better)
Please assume that there is no analytic function like lag() and unable to use pl/sql.
I have to solve this problem with basic sql statements.
I have a quite simple sql query to solve this kind of problem as follow:
select t1.col as col1, min(t2.col) as col2
from table1 t1 inner join table1 t2 on t2.col > t1.col
group by t1.col
order by t1.col
But this query is working when we assume there is no duplication.
Please help. Any comment or idea would be very thankful.
You can use a ROW_NUMBER to achieve this:
SELECT a.col,b.col
FROM (SELECT col,ROW_NUMBER () OVER (ORDER BY (SELECT 1)) 'Row_Rank'
FROM Table1
)a
LEFT JOIN (SELECT col,ROW_NUMBER () OVER (ORDER BY (SELECT 1)) 'Row_Rank'
FROM Table1
)b
ON a.Row_Rank = b.Row_Rank - 1
Ideally you'd have something that you could segment this by, as it's nice to ensure ordering, but the above works. The ROW_NUMBER just creates a number for each row, which you can use to self-join with an offset of 1 row.
EDIT: Changed to LEFT JOIN, depending on what you want to return for the last record you can use LEFT or INNER, and you could wrap the selected columns in ISNULL if you wanted to return a specific value to be paired with the last value that has no next row.

SQL First Match or just First

Because this is part of a larger SQL SELECT statement, I want a wholly SQL query that selects the first item matching a criteria or, if no items match the criteria, just the first item.
I.e. using Linq I want:
Dim t1 = From t In Tt
Dim t2 = From t In t1 Where Criteria(t)
Dim firstIfAny = From t In If(t2.Any, t2, t1) Take 1 Select t
Because If is not part of Linq, LinqPad doesn't show a single SQL statement, but two, the second depending upon whether the Criteria matches any of the Tt values.
I know it will be SELECT TOP 1 etc. and I can add ORDER BY clauses to get the specific first one I want, but I'm having trouble thinking of the most straightforward way to get the first of two criteria. (It was at exactly this point when I was able to solve this myself.)
Seeing as I don't see an existing question for this, I will let it stand. I'm sure someone else will see the answer quickly.
select top 1 *
from (
select top 1 *, 1 as Rank from MyTable where SomeColumn = MyCriteria
union all
select top 1 *, 2 as Rank from MyTable order by MyOrderColumn
) a
order by Rank
I've gone with this:
SELECT TOP 1 *
FROM MyTable
WHERE SomeColumn = MyCriteria
OR NOT (EXISTS (SELECT NULL FROM MyTable WHERE SomeColumn = MyCriteria))
ORDER BY MyOrdering
My actual SomeColumn = MyCriteria is rather more complex of course, as well as other unrelated where clauses.