SQL server mismach columns - sql

I'm trying to write a query for SQL Server.
must sum two separate columns
if the column Debe is less than the column Haber should print "mismatch"
The explanation is :
There are two tables ContD and Cont with a common column ID
The table ContD has two important columns, Debe and Haber.
The table Cont has one important column, Importe
If the sum of Debe is not equal to the sum of Haber should report printing a message on another column.
If the final number Debe and Haber are equal, compared to the column Importe of the table Cont and print coincidence in another column
http://www.grupoalta.com/wp-content/uploads/queryconciliacion.png

This should do the trick:
Note: I have commented the script that you actually want to use, the uncommented script is a quick sample that I have made out of the screenshot you shared, but as #Horaciux said, please, include a sample the next time.
Note 2: I supposed that the id in your table Cont is the primary key or it is just Unique, meanwhile the id in the table contD is a foreign key or it just doesn't have the constraint of Uniqueness.
DECLARE #t1 AS TABLE (id NUMERIC,debe DECIMAL(18,2),haber DECIMAL(18,2))
DECLARE #t2 AS TABLE (id NUMERIC,importe DECIMAL(18,2))
INSERT INTO #t1
SELECT 10887,NULL,603.2 UNION ALL
SELECT 10887,83.2,NULL UNION ALL
SELECT 10887,520,NULL UNION ALL
SELECT 10888,NULL,21.344 UNION ALL
SELECT 10888,18.40,NULL UNION ALL
SELECT 10888,2.944,NULL
INSERT INTO #t2
SELECT 10887,603.2 UNION ALL
SELECT 10888,150
SELECT id
,SUM(debe) 'Debe'
,SUM(haber) 'Haber'
,(SELECT importe FROM #t2 where id=t1.id) 'Importe'
,CASE WHEN SUM(debe)=SUM(haber) THEN '' ELSE 'not equal' END 'Debe=Haber'
,CASE WHEN (SUM(debe)=SUM(haber) AND (SELECT importe FROM #t2 WHERE id=t1.id)=SUM(debe)) THEN 'Coincidence' ELSE '' END 'Debe=Haber=Importe'
FROM #t1 t1
GROUP BY id
/*
SELECT id
,SUM(debe) 'Debe'
,SUM(haber) 'Haber'
,(SELECT importe FROM #t2 where id=t1.id) 'Importe'
,CASE WHEN SUM(debe)<>SUM(haber) THEN 'not equal' ELSE '' END 'Debe=Haber'
,CASE WHEN (SUM(debe)=SUM(haber) AND (SELECT importe FROM cont WHERE id=t1.id)=SUM(debe)) THEN 'Coincidence' ELSE '' END 'Debe=Haber=Importe'
FROM contd t1
GROUP BY id
*/

here is an approach that does the comparison and returns one value, depending on the nature of the match. This uses a case statement:
select cd.id,
(case when cd.sumdebe <> cd.sumhaber then 'not equals'
when cd.sumdebe = c.importe then 'all same'
else 'mismatch'
end)
from (select id, sum(debe) as sumdebe, sum(haber) as sumhaber
from contd
group by id
) cd left outer join
cont c
on cd.id = c.id;

Related

Use result from case statement in another case statement in oracle

I have a view which contains a cast statement for one column. This cast statement contains a case statement. This statement works. The result of this statement is 1, 2, or 3.
From here, I need to use the result from the previous case statement (I used a WITH statement and it doesn't work) to determine the value of the column. A simple case statement that assigns yes, no or null to the above statement's value (1,2, or 3)
ANY help is appreciated. Thank you.
Example using pseudo-code:
CAST (
WITH case_output
AS(
SELECT
CASE
WHEN EXISTS
(select from table where blah blah)
THEN
(select column from that table)
ELSE
(select from some another table)
END
)
CASE
WHEN case_output = 1
THEN 'Yes'
WHEN case_output = 2
THEN 'No'
else
NULL
AS VARCHAR2 (10))
column_name,
.... [rest of query]
You're mixing up the query name and the column name of the WITH clause. For example, it's
WITH my_query AS (SELECT c1 AS my_column FROM t1)
SELECT my_column FROM my_query;
Secondly, you'll always need a FROM clause in Oracle's SQL. Use the dummy table DUAL as stand-in:
SELECT CASE WHEN ... THEN END AS my_column
FROM DUAL;
Minimal working example:
CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c2 INT);
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (2);
WITH case_query AS (
SELECT CASE WHEN EXISTS (SELECT * FROM t1 WHERE c1=100)
THEN (SELECT c1 FROM t1)
ELSE (SELECT c2 FROM t2)
END AS case_output
FROM dual)
SELECT CASE case_output
WHEN 1 THEN 'Yes'
WHEN 2 THEN 'No'
ELSE NULL
END second_case_output
FROM case_query;

Is there a way to return all unique values within a given row

I am working in Oracle SQL and I have a data set with these headers
In this data set card number is unique, however, the customer can have duplicates in their Suggestion fields. Rather than going through and writing case statements, is there a way to keep only the unique values within the given row?
Please note, some customers will be left with more "unique" suggestions than others
For example:
My goal would be for my final output to look like this
As I have mentioned, previously, I would just write case statements saying
SELECT DISTINCT CARD_NUMBER
,SUGGESTION_1
,CASE
WHEN SUGGESTION_2 != SUGGESTION_1
THEN SUGGESTION_2
WHEN SUGGESTION_3 != SUGGESTION_1
THEN SUGGESTION_3
WHEN SUGGESTION_4 != SUGGESTION_1
THEN SUGGESTION_4
WHEN SUGGESTION_5 != SUGGESTION_1
THEN SUGGESTION_5
END AS SUGGESTION_2
CASE
WHEN SUGGESTION_2 != SUGGESTION_1
AND SUGGESTION_3 != SUGGESTION_1
AND SUGGESTION_3 != SUGGESTION_2
THEN SUGGESTION_3
`
I would do this until all unique values are left, and there just has to be an easier way
Any help would be EXTREMELY appreciated, thank you!
You can use union all and conditional aggregation. Here is the idea that puts the results in a single column:
select card, listagg(suggestion, ', ') within group (order by which) as suggestions
from (select card, suggestion, min(which) as which
from ((select card, 1 as which, suggestion_1 as suggestion from t) union all
(select card, 2, suggestion_2 from t) union all
(select card, 3, suggestion_3 from t) union all
(select card, 4, suggestion_4 from t) union all
(select card, 5, suggestion_5 from t)
) t
group by card, suggestion
) t
group by card;
You can do something similar with conditional aggregation if you want the values in separate columns.
I would try to pivot the table to long, and then back to wide
Setup:
create table testtbl
(
CARD_NUMBER int
,SUGGESTION_1 varchar2(100)
,SUGGESTION_2 varchar2(100)
,SUGGESTION_3 varchar2(100)
,SUGGESTION_4 varchar2(100)
,SUGGESTION_5 varchar2(100)
);
insert into testtbl values (1234,'G11','G4','G3','G2','G6');
insert into testtbl values (5678,'G4','G6','G6','G11','G6');
insert into testtbl values (9101,'G1','G3','G11','G4','G11');
Then the Query itself, first the pivoting to long. Here I use a function just to return the numbers from 1 to 5 - this is instead of joining the table 5 times to itself, this way it should only pass through the test table once.
I then use the analytical functionrow_number to sort the unique values according to their first placement.
The second select uses MAX to pivot back to wide
with cte AS
(
SELECT
CARD_NUMBER
,MIN(n.column_value ) n
,CASE n.column_value
WHEN 1 THEN f.SUGGESTION_1
WHEN 2 THEN f.SUGGESTION_2
WHEN 3 THEN f.SUGGESTION_3
WHEN 4 THEN f.SUGGESTION_4
WHEN 5 THEN f.SUGGESTION_5
END Suggestion
,ROW_NUMBER() OVER (PARTITION BY f.CARD_NUMBER ORDER BY MIN(n.column_value)) rn
FROM testtbl f
CROSS JOIN table(sys.odcinumberlist(1,2,3,4,5)) n
GROUP BY f.CARD_NUMBER,CASE n.column_value
WHEN 1 THEN f.SUGGESTION_1
WHEN 2 THEN f.SUGGESTION_2
WHEN 3 THEN f.SUGGESTION_3
WHEN 4 THEN f.SUGGESTION_4
WHEN 5 THEN f.SUGGESTION_5
END
)
SELECT
CARD_NUMBER
,MAX(CASE WHEN rn=1 THEN Suggestion ELSE '' end)SUGGESTION_1
,MAX(CASE WHEN rn=2 THEN Suggestion ELSE '' end)SUGGESTION_2
,MAX(CASE WHEN rn=3 THEN Suggestion ELSE '' end)SUGGESTION_3
,MAX(CASE WHEN rn=4 THEN Suggestion ELSE '' end)SUGGESTION_4
,MAX(CASE WHEN rn=5 THEN Suggestion ELSE '' end)SUGGESTION_5
FROM cte
GROUP BY CARD_NUMBER
ORDER BY CARD_NUMBER

How best to Count(*) with a CASE STATEMENT?

The following SQL (on SQL Server) returns an error of:
Incorrect syntax near '*'
Is there something inherently wrong with using the following SELECT statement?:
SELECT
COUNT(CASE WHEN <conditions> THEN * ELSE NULL END) as conditionalcountall
FROM TABLE
I tried this variation which also failed:
SELECT
CASE WHEN <conditions> THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM TABLE
I tend to like sum()
SELECT
SUM(CASE WHEN <conditions> THEN 1 ELSE 0 END) as conditionalcountall
FROM TABLE
Try This, it is Tested
SELECT
CASE WHEN 1 = 1 THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM TABLE
1 = 1is example conditions
Demo:-
Create table #temp (id int , col1 varchar (10))
go
insert into #temp values (1 , 'aaaa')
insert into #temp values (2 , 'bbbb')
insert into #temp values (3 , 'cccc')
SELECT
CASE WHEN 1 = 1 THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM #temp
Result:
In Case Condation like that id = 1 you should select Count(*) in CASE cluse in your query
like this:
SELECT
CASE WHEN id = 1 THEN (select COUNT(*) from #temp) ELSE NULL END as conditionalcountall
FROM #temp
Result:-
Note: if You used Count(*) directly, you counted the id column, so you should use group by as next:
SELECT
CASE WHEN id = 1 THEN COUNT(*) ELSE NULL END as conditionalcountall
FROM #temp
group by id
Result:
SELECT
CASE WHEN X THEN Y
ELSE Z
END *NEW COLUMN NAME*
, COUNT(*)
FROM
TABLE
GROUP BY
*NEW COLUMN NAME*
This should return two columns, one with the buckets/case statement and one with the count of the columns for each one of your buckets
This method was the most straightforward for myself
If you REALLY, REALLY want to use COUNT, then you can do this:
SELECT
COUNT(*)
FROM table
WHERE <conditions>

Search SQL and return true or false

I have a table that has thousands of rows in. I need to check if certain values exists in the table or not.
I want to list all the bar codes I am searching with a flag of true or false returned if there is one.
I have come up with this so far:
SELECT CASE WHEN EXISTS (
SELECT *
FROM TABLE
WHERE Coulmn in ('a','b', 'c', 'd', 'e', 'f', 'g')
)
THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT) END
This however just returns a value of 1.
So in the table I have
coulmn
----------
A
B
D
E
F
G
I want to do a search that returns the following
Coulmn | Exsists
-----------------
A | True
B | True
C | False
D | True
E | True
F | True
G | True
You can use a query like the following:
SELECT t1.v,
CASE WHEN t2.col IS NOT NULL THEN 'true' ELSE 'false' END AS Exists
FROM (
SELECT 'a' AS v UNION ALL SELECT 'b' UNION ALL SELECT 'c' UNION ALL SELECT 'd'
UNION ALL SELECT 'e' UNION ALL SELECT 'f' UNION ALL SELECT 'g') AS t1
LEFT JOIN mytable AS t2 ON t1.v = t2.col
This works:
SELECT *, CASE WHEN (Column in ('1','2')) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END AS result_field
FROM TABLE;
NOTE: Tested in PostgreSQL
As it's written, the outer select is select case when exists () then 1 else 0 end... so it is only going to return one row. The outer select must include "Column" AND "Exists" (select column, ...) to return two columns.
A "where" clause will never return a "false" like this, though, because "column" has to be in a real table for the query to actually return it. As #jarlh says, you'll need a helper table to store the columns you're looking for:
Create table SearchColumns (SearchColumn char(1));
insert into SearchColumns (SearchColumn)
values ('A'), ('B'), ('C'), ('D'), ('E'), ('F'), ('G'), ('H')
Then you can do the If Exists to your table from that table to see which values are in or not in:
select SearchColumn, case when exists
(select * from TABLE where Table.Column = SearchColumns.SearchColumn)
then 'True' else 'False' end as ExistsStatus
from SearchColumns
I think that will get you what you want. This gets a) Only one record per column no matter how many times it occurs in your table and b) "True" and "False" for every column value you're looking for. If you really wanted a Bit, you can use 0 and 1 and the casting from the original query, but they actually show "0" and "1"; and c) this should work no matter how many values you have.
(Note, I assumed some of those were spelling errors, so I made adjustments, but they were consistent so I'm not certain).
With the help form above I created a temp table and then implemented one of the soultions shared.
CREATE TABLE #Temp
(
Barcode VARCHAR (100)
)
INSERT INTO #Temp
VALUES
(1),
(2),
(3),
(4 )
select barcode, case when exists
(select * from CIPKORHHTProductDetails where CIPKORHHTProductDetails.Barcode = #temp.barcode)
then 'True' else 'False' end as ExistsStatus
from #temp order by ExistsStatus DESC

Joining a Temp Table to Actual Table

I need to verify that each order has been acknowledged. The problem is that each order can have multiple codes. The query I had (utilizing a CASE statement) would check for blank fields or fields with the string "None" to verify the order has not been acknowledged. It would return the appropriate result, but multiple rows (once for each possible response) and I only need (1).
I'm attempting to create a temp table that will return the appropriate result and join (via an order unique ID) the two tables together hoping to correct the multiple row issue. Here is the code:
DROP TABLE staging_TABLE;
CREATE TEMP TABLE staging_TABLE(
ORDERID varchar(256) ,
CODE varchar(256) );
/*Keeping data types consistent with the real table*/
INSERT INTO staging_TABLE
SELECT ORDERID,
CASE CODE
WHEN 'None' THEN 'No'
WHEN '' THEN 'No'
ELSE 'Yes'
END
FROM ORDERS
WHERE UTCDATE > SYSDATE - 10
AND CODE IS NOT NULL;
SELECT R.QUESTION,
R.ORDERNAME,
T.CODE
FROM ORDERS R
INNER JOIN staging_TABLE T
ON R.ORDERID= T.ORDERID
WHERE R.UTCDATE > SYSDATE - 10
AND R.CODE IS NOT NULL
AND R.CATEGORY IS NOT NULL
AND R.UTCDATE IS NOT NULL
GROUP BY
R.ORDER,
T.CODE,
R.ORDERNAME,
R.CODE
ORDER BY
R.ORDERNAME,
R.ORDER;
Am I doing this correctly? Or is this even the right approach?
Am I doing this correctly? Or is this even the right approach?
No. You don't need a temp table for this. Your query might look like this:
SELECT question, ordername
, CASE WHEN code IN ('None', '') THEN 'No' ELSE 'Yes' END AS code
FROM orders
WHERE utcdate > sysdate - 10
AND code IS NOT NULL
AND category IS NOT NULL
GROUP BY question, ordername, 3, "order"
ORDER BY ordername, "order";
ORDER is a reserved word. It's not possible to use it as column name unless double quoted. There is something wrong there.
AND R.UTCDATE IS NOT NULL is redundant. It can't be NULL anyway with WHERE R.UTCDATE > SYSDATE - 10
3 in my GROUP BY clause is a positional reference to the CASE expression. Alternatively you can spell it out again:
....
GROUP BY question, ordername
, CASE WHEN code IN ('None', '') THEN 'No' ELSE 'Yes' END
, "order"
You can use the DISTINCT keyword as follows so you will not need a temp table:
SELECT DISTINCT QUESTION,
ORDERNAME,
CASE CODE
WHEN 'None' THEN 'No'
WHEN '' THEN 'No'
ELSE 'Yes'
FROM ORDERS
WHERE UTCDATE > SYSDATE - 10
AND CODE IS NOT NULL
AND CATEGORY IS NOT NULL
AND UTCDATE IS NOT NULL
ORDER BY 2,3;