SQL query with exists and count for many fields in subquery - abap

I have this query:
SELECT *
FROM j_1gvl_ml AS jml
WHERE sptag IN #s_sptag AND
bukrs = #p_bukrs AND
werks IN #s_werks AND
matnr IN #s_matnr AND
tract IN #s_tract AND
erdat IN #s_erdat AND
repid = #p_repid AND
EXISTS ( SELECT vrsio,whbcode,bukrs,belnr,buzei,
werks,locat,matnr,bwtar,orgn, COUNT( * )
FROM j_1gvl_ml
WHERE vrsio = jml~vrsio AND
sptag = jml~sptag AND
whbcode = jml~whbcode AND
bukrs = jml~bukrs AND
belnr = jml~belnr AND
buzei = jml~buzei AND
werks = jml~werks AND
locat = jml~locat AND
matnr = jml~matnr AND
bwtar = jml~bwtar AND
orgn = jml~orgn
GROUP BY vrsio,whbcode,bukrs,belnr,buzei,
werks,locat,matnr,bwtar,orgn
HAVING COUNT( * ) > 1 )
INTO TABLE #itj_1gvl_ml.
There is an error that I cannot have more than 1 field in subquery.
I know that I can have 2 queries with for all entries. But I am looking if there is possible, to have in 1 query to have only the double, triple etc records.
Is this possible?

An EXISTS subquery is there to qualify which rows you want to select. It does not add rows or columns to the result set.
Reduce the list of columns in the SELECT clause of your sub query to any single one of the columns, or even a literal - such as SELECT 1 - and you will get your duplicates:
SELECT *
FROM j_1gvl_ml AS jml
WHERE sptag IN #s_sptag AND
bukrs = #p_bukrs AND
werks IN #s_werks AND
matnr IN #s_matnr AND
tract IN #s_tract AND
erdat IN #s_erdat AND
repid = #p_repid AND
EXISTS ( SELECT belnr
FROM j_1gvl_ml
WHERE vrsio = jml~vrsio AND
sptag = jml~sptag AND
whbcode = jml~whbcode AND
bukrs = jml~bukrs AND
belnr = jml~belnr AND
buzei = jml~buzei AND
werks = jml~werks AND
locat = jml~locat AND
matnr = jml~matnr AND
bwtar = jml~bwtar AND
orgn = jml~orgn
GROUP BY vrsio,whbcode,bukrs,belnr,buzei,
werks,locat,matnr,bwtar,orgn
HAVING COUNT( * ) > 1 )
INTO TABLE #itj_1gvl_ml.

Related

Divide the results of two select queries

I have two SQL count queries that on their own work fine, they are:
SELECT count(*) AS TOTAL_PROGRESS_BY_LINE_
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C'
RESULT: TOTAL_PROGRESS_BY_LINE_ = 26
SELECT count(*) AS TOTAL_LINES_BY_PROJECT_
FROM dbo.PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234'
RESULT: TOTAL_LINES_BY_PROJECT_ = 130
Now how to do I add to the query to get the percentage of 26/130??
I have a new query to go along with how to get percentages.
Here it is:
SELECT ISOGEN_LINE_PROGRESS_, PROJECT_NUMBER_,
CASE
WHEN ISOGEN_LINE_PROGRESS_ = 'A' THEN 'NOT IN MODEL'
WHEN ISOGEN_LINE_PROGRESS_ = 'B' THEN 'ROUGHED IN'
WHEN ISOGEN_LINE_PROGRESS_ = 'C' THEN 'PARTIAL CHECK'
WHEN ISOGEN_LINE_PROGRESS_ = 'D' THEN 'READY FOR FINAL CHECK'
WHEN ISOGEN_LINE_PROGRESS_ = 'E' THEN '100% COMPLETE'
WHEN ISOGEN_LINE_PROGRESS_ = '0' THEN 'ISSUE FOR CONSTRUCTION'
END AS PROGRESS_PER_LINE_
FROM PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234'
ORDER BY ISOGEN_LINE_PROGRESS_
this brings back results below:
ISOGEN_LINE_PROGRESS_ PROJECT_NUMBER_ PROGRESS_PER_LINE_
A PJ001234 NOT IN MODEL
B PJ001234 ROUGHED IN
C PJ001234 PARTIAL CHECK
D PJ001234 READY FOR FINAL CHECK
If I remove the Distinct from my query there are obviously multiple rows for each level of progress. How do I add to the above distinct query to have a column at the end with the rate or percent of each level of progress compared to the overall number of lines?
Select them as a subquery.
By default the result will be an integer because count(*) returns an int. For a decimal result convert to a decimal.
SELECT (
SELECT CONVERT(decimal(9,2),COUNT(*)) AS TOTAL_PROGRESS_BY_LINE_
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C'
) / (
SELECT CONVERT(decimal(9,2),COUNT(*)) AS TOTAL_LINES_BY_PROJECT_
FROM dbo.PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234'
)
You may use conditional aggregation and simple division in one query:
select
100.0 *
count(
case when ISOGEN_LINE_PROGRESS_ = 'C'
then 1
end
)
/
nullif(count(
case when PROJECT_NUMBER_ = 'PJ001234'
then 1
end
), 0) as rate_
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C'
or PROJECT_NUMBER_ = 'PJ001234'
DECLARE #firstone INT;
DECLARE #secondone INT;
SELECT #firstone = count(*)
FROM dbo.PID_Components_PROCESS_LINES
WHERE ISOGEN_LINE_PROGRESS_ = 'C';
SELECT #secondone = count(*)
FROM dbo.PID_Components_PROCESS_LINES
WHERE PROJECT_NUMBER_ = 'PJ001234';
SELECT #firstone / #secondone AS resultthing
SELECT #firstone /CAST(#secondone AS DECIMAL (9,2))
You could use a common table expression to get the counts and then select the desired results in one swell foop:
with Counts as (
select
( select Count(*) from Sys.Tables ) as NumberOfTables,
( select Count(*) from Sys.Columns ) as NumberOfColumns
)
select NumberOfTables, NumberOfColumns,
NumberOfColumns / NumberOfTables as ColumnsPerTable,
( 100 * NumberOfColumns ) / NumberOfTables as IntegerPercentColumnsPerTable,
( 100.0 * NumberOfColumns ) / NumberOfTables as NumericPercentColumnsPerTable
from Counts;
I used existing tables since you chose not to supply DDL and sample data. So it goes.

How to SELECT WHERE EXISTS in multi table?

I have 3 tables:
/test/table1:
Columns: doc_id, anotherID, value1
/test/table2:
Columns: anotherID, value1
/test/table3
Columns: doc_id, value2
I want to select the data of /test/table1 with 2 conditions. One condition in /test/table2 and another one in /test/table3.
So I select my data in one table with one condition like that:
SELECT doc_id, anotherID FROM /test/table1 AS d
INTO CORRESPONDING FIELDS OF TABLE #ct_document
WHERE EXISTS ( SELECT * FROM /test/table2 AS a
WHERE value1 < #iv_value1 AND a~value1 = d~value1_id ).
It selects the content as I expect. But now I want to add a condition, to only select this data but only where /test/table3~value2 = 2.
To do that, I do:
SELECT doc_id, anotherID FROM /test/table1 AS d
INTO CORRESPONDING FIELDS OF TABLE #ct_document
WHERE EXISTS ( SELECT * FROM /test/table2 AS a
WHERE value1 < #iv_value1 AND a~value1 = d~value1_id )
AND EXISTS ( SELECT * FROM /test/table3 AS e
WHERE e~value2 = 2 ).
When I do that, I have the same content as before... It doesn't take my second condition.
What don't I understand ?
The condition EXISTS ( SELECT * FROM /test/table3 AS e WHERE e~value2 = 2 ) is always evaluated to TRUE if there's at least one line in /test/table3 with e~value2 = 2, whatever the content of the table /test/table1.
To make it evaluated to TRUE or FALSE according to /test/table1 (alias d), you should add the condition AND e~doc_id = d~doc_id, like this:
...
AND EXISTS ( SELECT * FROM /test/table3 AS e
WHERE e~value2 = 2 AND e~doc_id = d~doc_id ).

Select the first row that meets a condition + 1 row above

I have written a SQL query to return the following results:
Rows returned
However, I need to further 'filter' it down to only the rows highlighted in yellow, because I want the first row that has param_id = 'update_flag' AND param_val = '1'. I also need the row above that, because I need to retrieve the param_val value (202017) that corresponds to param_id = 'period_from' for the same Order Number (156 in this example).
This is my code, I'm getting data from 2 different tables:
SELECT
report1.orderno AS t1_orderno,
report2.orderno AS t2_orderno,
report1.report_name AS t1_reportname,
report2.report_name AS t2_reportname,
report1.variant,
report1.status,
report1.client,
report2.param_id,
report2.param_val
FROM report1
INNER JOIN
report2
ON report1.orderno = report2.orderno
AND report2.param_id IN
(
'period_from',
'update_flag'
)
AND report1.report_name = 'PR28'
AND report1.variant = '20'
AND report1.status = 'T'
AND report1.client = '10'
ORDER BY
report1.orderno DESC
Thanks for any help in advance, it's doing my head in!
WITH num_row AS (
SELECT row_number() OVER (ORDER BY report1.orderno DESC) as nom,
report1.orderno AS t1_orderno,
report2.orderno AS t2_orderno,
report1.report_name AS t1_reportname,
report2.report_name AS t2_reportname,
report1.variant,
report1.status,
report1.client,
report2.param_id,
report2.param_val
FROM report1
INNER JOIN
report2
ON report1.orderno = report2.orderno
AND report2.param_id IN (
'period_from',
'update_flag'
)
AND report1.report_name = 'PR28'
AND report1.variant = '20'
AND report1.status = 'T'
AND report1.client = '10'
)
SELECT * FROM num_row
WHERE nom BETWEEN 1 AND 2

Selecting specific cells from multiple tables

I am trying to select specific cells from 3 different tables.
I have 3 different queries but whenever I run them it crashes a while and I was wondering if maybe I could combine them into one query.
SELECT * FROM INFM_DALI_BBM_CSC2.MARA_BBM
WHERE MANDT = '011'
AND MTART IN ('HALB','FERT')
AND "/RB04/YERZKENNZ" in ('EZ','BG','TS')
AND LOGSYS in ('SAPP72011', 'SAPPOE011');
SELECT * FROM INFM_DALI_BBM_CSC2.MARC_BBM
WHERE MANDT = '011'
AND BESKZ IN ('E','F')
AND WERKS in ('8640','864W','E499')
AND LOGSYS in ('SAPP72011', 'SAPPOE011');
SELECT * FROM INFM_DALI_BBM_CSC2.MBEW_BBM
WHERE MANDT = '011'
AND BKLAS IN ('7900','7920')
AND LOGSYS in ('SAPP72011', 'SAPPOE011');
The table should get the values that are on this table.
https://drive.google.com/file/d/1TSFJbpBsPJ5ZG61ULX6WumdNt1DUPJXO/view?usp=sharing
Consider this :
SELECT * FROM INFM_DALI_BBM_CSC2.MARA_BBM
WHERE MANDT = '011'
AND LOGSYS IN ('SAPP72011', 'SAPPOE011')
AND ( ( MTART IN ('HALB','FERT') AND "/RB04/YERZKENNZ" IN ('EZ','BG','TS') ) OR
( BESKZ IN ('E','F') AND WERKS IN ('8640','864W','E499') ) OR
( BKLAS IN ('7900','7920') ) )

Need help creating SQL query from example of data

I have a database table below.
And I want to get list of all DBKey that have: at least one entry with Staled=1, and the last entry is Staled=0
The list should not contain DBKey that has only Staled=0 OR Staled=1.
In this example, the list would be: DBKey=2 and DBKey=3
I think this should do the trick:
SELECT DISTINCT T.DBKey
FROM TABLE T
WHERE
-- checks that the DBKey has at least one entry with Staled = 1
EXISTS (
SELECT DISTINCT Staled
FROM TABLE
WHERE DBKey = T.DBKey
AND Staled = 1
)
-- checks that the last Staled entry for this DBKey is 0
AND EXISTS (
SELECT DISTINCT Staled
FROM TABLE
WHERE DBKey = T.DBKey
AND Staled = 0
AND EntryDateTime = (
SELECT MAX(EntryDateTime)
FROM TABLE
WHERE DBKey = T.DBKey
)
)
Here is a working SQLFiddle of the query, using your sample data.
The idea is to use EXISTS to look for those individual conditions that you've described. I've added comments to my code to explain what each does.
Should be done with a simple JOIN... Starting FIRST with any 1 qualifiers, joined to itself by same key AND 0 staled qualifier AND the 0 record has a higher date. Ensure you have an index on ( DBKey, Staled, EntryDateTime )
SELECT
YT.DBKey,
MAX( YT.EntryDateTime ) as MaxStaled1,
MAX( YT2.EntryDateTime ) as MaxStaled0
from
YourTable YT
JOIN YourTable YT2
ON YT.DBKey = YT2.DBKey
AND YT2.Staled = 0
AND YT.EntryDateTime < YT2.EntryDateTime
where
YT.Staled = 1
group by
YT.DBKey
having
MAX( YT.EntryDateTime ) < MAX( YT2.EntryDateTime )
Maybe this:
With X as
(
Select Row_Number() Over (Partition By DBKey Order By EntryDateTime Desc) RN, DBKey, Staled
From table
)
Select *
From X
Where rn = 1 and staled = 0 and
Exists (select 1 from x x2 where x2.dbkey = x.dbkey and Staled = 1)