<SQL> How to edit EXISTS query - sql

I have a query that has EXISTS query, which has PRCS_STE_CD column.
QUERY
SELECT
PRCS_SNO
, YEAR
, SUBSC_CANC_YN
FROM
TB_POT_ECD_PRCS_INFO INF
WHERE
INF.SUBSC_CANC_YN = 'N'
AND EXISTS (
SELECT 'X'
FROM TB_POT_ECD_PRCS_HIST HIS
WHERE PRCS_STE_CD = 'R01'
)
Idea is to show only ones that PRCS_STE_CD = 'R01'.
But the problem is that some have 'R01' and 'R02' for PRCS_STE_CD.
(In this case, where it has both R01 and R02, I do not want to show it on the list.)
Basiacally, I want to show one that only has R01 for PRCS_STE_CD.
Oh and PRCS_STE_CD CAN NOT have only R02. It must have R01 in order to have R02.
And again, when it has both R01, R02, it should not be selected on the list.
Can anyone help editing the query?

In your table how have you stored R02 for PRCS_STE_CD. I assume you have a different column to store R02. If so then you can try using the IN and the OR Operators as.
SELECT
PRCS_SNO, YEAR, SUBSC_CANC_YN
FROM TB_POT_ECD_PRCS_INFO INF
WHERE INF.SUBSC_CANC_YN = 'N'
AND 'X' IN (
SELECT 'X'
FROM TB_POT_ECD_PRCS_HIST HIS
WHERE PRCS_STE_CD = 'R01' OR Second_Column= 'R02'
)

Related

Get different query back based on a condition in PostgreSQL

I'm having a hard time with sql and probably this will look stupid but it shows what I am trying to achieve.
SELECT
CASE WHEN ( ( SELECT 1 FROM table_1 WHERE = condition ) IS NULL ) THEN
SELECT 'No result'::varchar
ELSE
SELECT
val_1,
val_2,
val_3
FROM
table_1
END;
A null answer is not good in my situation, I can't just use the sub-query as the main. And even if I could that would still leave the question open if the two tables were NOT the same like:
SELECT
CASE WHEN ( ( SELECT 1 FROM table_1 WHERE = condition ) IS NULL ) THEN
SELECT 'No result'::varchar
ELSE
SELECT
val_1,
val_2,
val_3
FROM
table_2 --TABLE REPLACED!
END;
As CASE-WHEN only works for one column it would be horrifying to have 20 of them with the same condition. Any help is appreciated! Thanks!
So you want to SELECT the table_log and if the result is not NULL show it to the client and if it is NULL show a message?
I created a fake table for testing. What you are looking for is the last SELECT-statement:
DROP TABLE IF EXISTS table_log;
CREATE TEMP TABLE table_log (
id INTEGER
,log_info VARCHAR)
;
INSERT INTO table_log VALUES
(1, 'test_entry')
;
ANALYZE table_log;
SELECT
COALESCE(b.log_info, 'No changes done!') AS log_info
FROM
(SELECT 'Fake-Data') a
LEFT OUTER JOIN (SELECT * FROM table_log WHERE id = 1) b ON (1=1);
If the given id = 1, you get the result, if it is something else (because it is not in the test-table) the premade message is given.
Here is a link to the db<>fiddle.

Union a table with a synthetic table to get result even if query result is empty

I have a data table which i want to select some fields filtering by date.
If the result is empty, based on the sysdate I need to decide if it is ok or not.
To be able to do that I am creating a synthetic table with a flag field which I expect to be populated in result set even if there is no data in my actual table at that date.
WITH const AS (
SELECT
'NAME 1' AS name,
(CASE WHEN TO_TIMESTAMP(TO_CHAR(CURRENT_TIMESTAMP, 'HH24:MI:SS'), 'HH24:MI:SS') < TO_TIMESTAMP('01:00:00', 'HH24:MI:SS') THEN 1 ELSE 0 END) AS flag
FROM
Data_Table
UNION
SELECT
'ANY NAME' AS name,
(CASE WHEN TO_TIMESTAMP(TO_CHAR(CURRENT_TIMESTAMP, 'HH24:MI:SS'), 'HH24:MI:SS') < TO_TIMESTAMP('01:00:00', 'HH24:MI:SS') THEN 1 ELSE 0 END) AS flag )
SELECT Data_Table.sysname, const.flag FROM const LEFT OUTER JOIN Data_Table ON Data_Table.sysname = const.name WHERE Data_Table.date=TO_CHAR(sysdate, 'DD-MM-YYYY')
I expect to get results like below:
sysname flag
Name1 1
(null) 1
But getting empty result if there is no data with that date.
Here's general example. If I understand correctly you need to be able to return a value even if query returns no rows:
SELECT table_name FROM all_tables
WHERE table_name = 'YOUR_TABLE'
UNION ALL
SELECT '1' table_name FROM dual
WHERE NOT EXISTS
(
SELECT table_name FROM all_tables
WHERE table_name = 'YOUR_TABLE'
)
/
The result is 1 as there is no table as 'YOUR_TABLE' in my database. But if I put a valid table name then i will get results from the top query. If not then always get 1 or any other value from second query. The table names in both queries must be the same. The second one is a copy of the top one.
I see the problem in your last statement that is
SELECT Data_Table.sysname, const.flag
FROM const
LEFT OUTER JOIN Data_Table
ON Data_Table.sysname = const.name
WHERE Data_Table.date=TO_CHAR(sysdate, 'DD-MM-YYYY')-- Here is the problem
You are doing a left outer join and then filtering the data using where condition, the where condition will never be true in this case. You need to push that condition into the join so that it does not affect the overall result:
SELECT Data_Table.sysname, const.flag
FROM const
LEFT OUTER JOIN Data_Table
ON Data_Table.sysname = const.name
AND Data_Table.date=TO_CHAR(sysdate, 'DD-MM-YYYY')

Adding a new computed variable back to main dataset in SQL

I am trying to compute a variable (say last_week) and add it back to my main dataset (say new_j). I managed to join it to new_j. However, if I want to use that variable (last_week) now for further calculations, it does not recognise it. Here's my code:
SELECT [Weekkey] AS weekkey
,[article / colour] as prod_id
,[Current MP Department No/Desc] as prod_dept
,[Total Stock] as total_stock
INTO #new_j
FROM [J_20160831] --(that’s the db in server and I created a temp db #new_j)
SELECT prod_id, max(weekkey) as last_week
into #lastweeksales
FROM #new_j
group by prod_id
select *
from #new_j
left join #lastweeksales
on #lastweeksales.prod_id = #new_j.prod_id
So, I joined both successfully and if I run this code, I see column last_week. Now what I want to do is this:
select *
,case
when last_week = max(weekkey) then total_stock
else 0
end as last_stock_position
from #new_j
But it says last_week is not found in new_j. I also tried #lastweeksales.last_week instead of just last_week in the last bit of code, but it didn't either. What's the best way out here? Moreover, is there a better way to do it instead?. The output I am looking to have at the end is a table with these variables: WeekKey, prod_dept, prod_id, total_stock, last_week, last_stock_position
Thanks for the help!!! Much appreciate it.
This normal behaviour of joins..
by selecting this
select * from #new_j left join #lastweeksales
on #lastweeksales.prod_id = #new_j.prod_id'
all the columns of newj and lastweekales will be displayed in same order (first new_j columns and then lastweeksales columns ).So 'last_week' is the last column of lastweeksales.
Secondly,
select *,
case when last_week = max(weekkey) then total_stock
else 0
end as last_stock_position
from #new_j
in above query,your are selecting 'last_week' column which belongs to the table #lastweeksales.
Be careful while selecting the columns.
I guess your expecting,
select a.WeekKey, a.prod_dept, a.prod_id, a.total_stock, b.last_week,
case
when b.last_week = max(a.weekkey) then total_stock
else 0
end as last_stock_position
from #new_j as a
left join #lastweeksales as b
on b.prod_id = a.prod_id
group by a.weekkey,a.prod_dept,a.prod_id,a.total_stock,b.last_week

SQL when one column has duplicate rows, then select row where other column is the min value

I have this table
mt.id, mt.otherId, mt.name, mt.myChar, mt.type
1 10 stack U "question"
2 10 stack D
3 30 stack U "question"
4 10 stack U "whydownvotes"
And I want only
rows with id 2 and 3 returned (without using the id, otherid as parameter) and ensuring name and type are matching against parameters. And when there is a duplicate otherId = then return the row with min myChar value. So far I have this :
select mt.* from myTable mt
where (mt.myChar = 'U' AND (mt.name = 'stack' AND mt.type LIKE '%question%'))
or (mt.myChar = 'D' and mt.name = 'stack')
So where otherID is 10, I want the row with min char value 'D'. I am going to need a subquery or group using min(myChar) ... ?
How do i remove the first row from the sql fiddle (without using the id):
http://sqlfiddle.com/#!9/c579a/1
edit
Jeepers, whats with the downvotes, its clear question isn't it ? There is even a sql fiddle.
If this is SQL Server, then you can do it in two steps like this:
WITH filtered AS (
SELECT
mt.*,
minType = MIN(mt.type) OVER (PARTITION BY mt.otherId)
FROM
dbo.myTable AS mt
WHERE (mt.myChar = 'U' AND mt.name = 'stack' AND mt.type LIKE '%question%')
OR (mt.myChar = 'D' AND mt.name = 'stack')
)
SELECT
id,
otherId,
name,
myChar,
type
FROM
filtered
WHERE
type = minType
;
The filtered subquery is basically your current query but with an additional column that holds minimum type values per otherId. The main query filters the filtered set further based on the type = minType condition.
I am assuming you want is a groupwise maximum, one of the most commonly-asked SQL questions You can try as , This query should work on any DBMS. But If you are using the SQL SERVER then you can use the Row_Number() which is very easy to use.Here myTable is your table.
SELECT t0.*
FROM myTable AS t0
LEFT JOIN myTable AS t1 ON t0.otherId = t1.otherId AND t1.myChar < t0.myChar
WHERE t1.myChar IS NULL;
Here is sql fiddle

Select the rows that just inserted

How can I retrieve the row just inserted?
INSERT INTO LETTRE_VOIT
select rsVoit.NOID, NO_ORDRE, rsOrdre.CODE_DEST, rsOrdre.MODAL_MODE, rsOrdre.MODAL_PORT,
CASE rsOrdre.MODAL_PORT
WHEN 'false' THEN 'D'
ELSE 'P'
END,
rsOrdre.LIVRS_EXPRS,
CASE rsOrdre.LIVRS_EXPRS
WHEN 'false' THEN 'L'
ELSE 'E'
END,
rsOrdre.ENLEV_UNITE, LIBELLE, NBR_COLIS,POID,ENLEV_CREMB,ENLEV_DECL
from ORDRE rsOrdre
inner join
(
select CODE_DEST,MODAL_MODE, MODAL_PORT, LIVRS_EXPRS,ENLEV_UNITE, ROW_NUMBER() over (order by CODE_DEST) as NOID
from ORDRE
group by CODE_DEST,MODAL_MODE,MODAL_PORT,LIVRS_EXPRS,ENLEV_UNITE
) rsVoit on rsVoit.CODE_DEST = rsOrdre.CODE_DEST and rsVoit.MODAL_MODE = rsOrdre.MODAL_MODE
and rsVoit.MODAL_PORT = rsOrdre.MODAL_PORT and rsVoit.LIVRS_EXPRS = rsOrdre.LIVRS_EXPRS
and rsVoit.ENLEV_UNITE = rsOrdre.ENLEV_UNITE
LEFT JOIN T_UNITE ON rsOrdre.ENLEV_UNITE = T_UNITE.NOID
WHERE (STATUT_ORDRE = 3) AND IS_PRINT = 'false' AND (TRANSPORTEUR IN (SELECT ParsedString From dbo.ParseStringList(#Trans)))
order by rsVoit.NOID, NO_ORDRE
SELECT * FROM LETTRE_VOIT WHERE ???
For example:
I inserted 2, it return 2
and then I inserted 3, I want return 3 instead of 5 rows.
Thanks in advance.
Stev
PS: May be I need to use a stored procedure ?
I'm not 100% sure what exactly you want back.... but SQL Server has an OUTPUT clause that can output stuff from INSERT and UPDATE and DELETE statements:
INSERT INTO dbo.YourTable(col1, col2, ..., colN)
OUTPUT Inserted.Col1, Inserted.IDCol, Inserted.Col17
VALUES(val1, val2, ...., valN)
Here, you're inserting values and the inserted values for the IDCol (e.g. an INT IDENTITY column), Col1 and Col17.
If just getting back the results into your grid in Mgmt Studio is good enough - then use the OUTPUT clause! Read more about the OUTPUT clause on Books Online
If you are using SQL Server
And you know how many row inserted then go through
SELECT top 2 * FROM LETTRE_VOIT order by primaryKeyId desc
put the number of row inserted at place of 2.
It may be help you, If you know the number of inserted rows, and then you can provide the numbers with top keyword
How about saving the records in a variable before inserting them or adding a date field and retrieve them by date?