SQL for Selecting Data with Codition - sql

in need a fast SQL for selcting my Data.
I have a Table a which look like the following:
And another Table b which look like the following:
In au can specify which data from b i need. Its the Flag a.kba_inkl (I = Inclusiv, E = Excluisiv)
The Key From both Tables are the first four Columns.
The First Row from a means all Artikel from b which has b.art_be = a.kba_be.
The Second Row from a means without Artickles from b where b.art_be = a.kba_be and b.art_wg = a.kba_wg. And so on.
In a: 0 means ALL (From 1-99)
In b can't appear a 0
Table a:
|------|------|------|-------|--------|
|kba_be|kba_wg|kba_ag|kba_anr|kba_inkl|
|------|------|------|-------|--------|
|10 |0 |0 |0 |I |
|------|------|------|-------|--------|
|10 |10 |0 |0 |E |
|------|------|------|-------|--------|
|10 |20 |30 |0 |E |
|------|------|------|-------|--------|
|20 |10 |0 |0 |I |
|------|------|------|-------|--------|
|20 |0 |0 |0 |E |
|------|------|------|-------|--------|
Table b:
|------|------|------|-------|
|art_be|art_wg|art_ag|art_anr|
|------|------|------|-------|
|10 |20 |30 |40 |
|------|------|------|-------|
|10 |10 |1 |5 |
|------|------|------|-------|
|10 |5 |30 |20 |
|------|------|------|-------|
|10 |10 |80 |50 |
|------|------|------|-------|
|10 |60 |30 |60 |
|------|------|------|-------|
|20 |10 |50 |50 |
|------|------|------|-------|
|20 |60 |30 |60 |
|------|------|------|-------|
Result:
|------|------|------|-------|
|art_be|art_wg|art_ag|art_anr|
|------|------|------|-------|
|10 |5 |30 |20 |
|------|------|------|-------|
|10 |60 |30 |60 |
|------|------|------|-------|
|20 |10 |50 |50 |
|------|------|------|-------|
Does anybody has an Idea?
Many thanks in advance.
EDIT: Maybe the Table a should be grouped like this:
|------|------|------|-------|--------|
|kba_be|kba_wg|kba_ag|kba_anr|kba_inkl|
|------|------|------|-------|--------|
|10 |0 |0 |0 |I |
|------|------|------|-------|--------|
|20 |0 |0 |0 |E |
|------|------|------|-------|--------|
|10 |10 |0 |0 |E |
|------|------|------|-------|--------|
|20 |10 |0 |0 |I |
|------|------|------|-------|--------|
|10 |20 |30 |0 |E |
|------|------|------|-------|--------|
And then loop through the rows.

So there are 2 parts of the query inclusive and exclusive.
The exclusive can be implemented using minus operator.
with a as
(
select 10 kba_be,0 kba_wg,0 kba_ag,0 kba_anr,'I' kba_incl from dual union all
select 10 kba_be,10 kba_wg,0 kba_ag,0 kba_anr,'E' kba_incl from dual union all
select 10 kba_be,20 kba_wg,30 kba_ag,0 kba_anr,'E' kba_incl from dual
),
b as
(
select 10 art_be,20 art_wg,30 art_ag,0 art_anr from dual union all
select 10 art_be,10 art_wg,1 art_ag,5 art_anr from dual union all
select 10 art_be,5 art_wg,30 art_ag,20 art_anr from dual union all
select 10 art_be,10 art_wg,80 art_ag,50 art_anr from dual union all
select 10 art_be,60 art_wg,30 art_ag,60 art_anr from dual
)
select b.* from
a,b
where
a.kba_incl = 'I'
and b.art_be = a.kba_be
and (b.art_wg = a.kba_wg or a.kba_wg=0)
and (b.art_ag = a.kba_ag or a.kba_ag=0)
minus
select b.* from
a,b
where
a.kba_incl = 'E'
and b.art_be = a.kba_be
and (b.art_wg = a.kba_wg or a.kba_wg=0)
and (b.art_ag = a.kba_ag or a.kba_ag=0)
result
10 5 30 20
10 60 30 60

Related

Postgres - How to achieve UNION behaviour with UNION ALL?

I have a table with parent and child ids.
create table if not exists stack (
parent int,
child int
)
Each parent can have multiple children and each child can have multiple children again.
insert into stack (parent, child) values
(1,2),
(2,3),
(3,4),
(4,5),
(5,6),
(6,7),
(7,8),
(8,9),
(9,null),
(1,7),
(7,8),
(8,9),
(9,null);
The data looks like this.
|parent|child|
|------|-----|
|1 |2 |
|2 |3 |
|3 |4 |
|4 |5 |
|5 |6 |
|6 |7 |
|7 |8 |
|8 |9 |
|9 |NULL |
|1 |7 |
|7 |8 |
|8 |9 |
|9 |NULL |
I'd like to find all children. I can use a recursive cte with a UNION ALL.
with recursive cte as (
select
child
from
stack
where
stack.parent = 1
union
select
stack.child
from
cte
left join stack on
cte.child = stack.parent
where
cte.child is not null
)
select * from cte;
This gives me the result I'd like to achieve.
|child|
|-----|
|2 |
|7 |
|3 |
|8 |
|4 |
|9 |
|5 |
|NULL |
|6 |
However I'd like to include the depth / level and also the path for each node. I can do this using a different recursive cte.
with recursive cte as (
select
parent,
child,
0 as level,
array[parent,
child] as path
from
stack
where
stack.parent = 1
union all
select
stack.parent,
stack.child,
cte.level + 1,
cte.path || stack.child
from
cte
left join stack on
cte.child = stack.parent
where
cte.child is not null
)
select * from cte;
That gives me this data.
|parent|child|level|path |
|------|-----|-----|--------------------|
|1 |2 |0 |{1,2} |
|1 |7 |0 |{1,7} |
|2 |3 |1 |{1,2,3} |
|7 |8 |1 |{1,7,8} |
|7 |8 |1 |{1,7,8} |
|3 |4 |2 |{1,2,3,4} |
|8 |9 |2 |{1,7,8,9} |
|8 |9 |2 |{1,7,8,9} |
|8 |9 |2 |{1,7,8,9} |
|8 |9 |2 |{1,7,8,9} |
|4 |5 |3 |{1,2,3,4,5} |
|9 | |3 |{1,7,8,9,} |
|9 | |3 |{1,7,8,9,} |
|9 | |3 |{1,7,8,9,} |
|9 | |3 |{1,7,8,9,} |
|9 | |3 |{1,7,8,9,} |
|9 | |3 |{1,7,8,9,} |
|9 | |3 |{1,7,8,9,} |
|9 | |3 |{1,7,8,9,} |
|5 |6 |4 |{1,2,3,4,5,6} |
|6 |7 |5 |{1,2,3,4,5,6,7} |
|7 |8 |6 |{1,2,3,4,5,6,7,8} |
|7 |8 |6 |{1,2,3,4,5,6,7,8} |
|8 |9 |7 |{1,2,3,4,5,6,7,8,9} |
|8 |9 |7 |{1,2,3,4,5,6,7,8,9} |
|8 |9 |7 |{1,2,3,4,5,6,7,8,9} |
|8 |9 |7 |{1,2,3,4,5,6,7,8,9} |
|9 | |8 |{1,2,3,4,5,6,7,8,9,}|
|9 | |8 |{1,2,3,4,5,6,7,8,9,}|
|9 | |8 |{1,2,3,4,5,6,7,8,9,}|
|9 | |8 |{1,2,3,4,5,6,7,8,9,}|
|9 | |8 |{1,2,3,4,5,6,7,8,9,}|
|9 | |8 |{1,2,3,4,5,6,7,8,9,}|
|9 | |8 |{1,2,3,4,5,6,7,8,9,}|
|9 | |8 |{1,2,3,4,5,6,7,8,9,}|
My problem is that I have a lot of duplicate data. I'd like to get the same result as the UNION query but with the level and the path.
I tried something like
where
cte.child is not null
and stack.parent not in (cte.parent)
or
where
cte.child is not null
and not exists (select parent from cte where cte.parent = stack.parent)
but the first does not change anything and the second returns an error.
ERROR: recursive reference to query "cte" must not appear within a subquery
Any ideas? Thank you very much!
Your problem is inappropriate table data. Your table contains the information that 8 is a direct child to 7 twice for instance. I suggest you remove the duplicate data and implement a unique constraint on the pairs.
If you cannot do so for some reason, make the rows distinct in your query:
with recursive
good_stack as (select distinct * from stack)
,cte as
(
select
parent,
child,
0 as level,
array[parent,
child] as path
from good_stack
where good_stack.parent = 1
union all
select
good_stack.parent,
good_stack.child,
cte.level + 1,
cte.path || good_stack.child
from cte
left join good_stack on cte.child = good_stack.parent
where cte.child is not null and good_stack.child is not null
)
select * from cte;
Demo: https://dbfiddle.uk/?rdbms=postgres_13&fiddle=acb1d7a1a1d26c3fd9caf0e7dedc12b2
(You may also make the columns not nullable. The entries 9|null add no information. If the table were lacking these entries, 9 would still be without a child.)

Write SQL Server query

Help me please with query:
select *
from sc84 as nom
join sc319 as p on p.PARENTEXT = nom.id
join sc219 as pt on p.sp327 = pt.id
join _1SCONST as c on c.objid=p.id
As a result approximately such table
Car / price_base / 08-08-2016:13-40 / 100 /
Car / price_base / 08-08-2016:14-40 / 150 /
Car / price_base / 08-09-2016:13-40 / 190 /
Car / price_super / 08-09-2016:18-40 / 210 /
Car / price_super / 08-10-2016:13-40 / 290 /
I want to return
Car / price_base / 08-09-2016:13-40 / 190 /
Car / price_super / 08-10-2016:13-40 / 290 /
That is good, types of the price of date and their value. Prompt please how to get the last (the current price for each type of the price and each goods) tried options with group but there is obviously not enough skill.
nom.id - PK SKU
pt.id - PK price type
p.id -PK price
p.parentext - parent price (sku)
p.sp327 - FK to price type
date = date column
I am using SQL Server 2008.
Table structure
T=1SCONST |
----Columns-------
Name |Descr |Type|Length|Precision
F=ROW_ID |Row ID |I |0 |0
F=OBJID |ID obj(0-cons ) |C |9 |0
F=ID |ID parameter |I |0 |0
F=DATE |Fix date |D |0 |0
F=VALUE |valume |V |255 |0
F=DOCID |ID Document |C |9 |0
F=TIME |Time |I |0 |0
F=ACTNO |Action No |I |0 |0
F=LINENO_ |LineNo |S |0 |0
F=TVALUE | |C |3 |0
T=SC319 |
----Columns-------
Name |Descr |Type|Length|Precision
F=ROW_ID |Row ID |I |0 |0
F=ID |ID object |C |9 |0
F=PARENTEXT |Parent in other tabl|C |9 |0
F=ISMARK |Object is Marked for|L |0 |0
F=VERSTAMP |Version stamp |I |0 |0
F=SP6681 |(P)Âàëþòà |C |9 |0
F=SP6682 |(P)Ïðîöåíò |N |5 |2
F=SP327 |(P)ÒèïÖåí |C |9 |0
T=SC319 |Ñïðàâî÷íèê Öåíû |SC319 |R
# ----Columns-------
# Name |Descr |Type|Length|Precision
F=ROW_ID |Row ID |I |0 |0
F=ID |ID object |C |9 |0
F=PARENTEXT |Parent in other tabl|C |9 |0
F=ISMARK |Object is Marked for|L |0 |0
F=VERSTAMP |Version stamp |I |0 |0
F=SP6681 |(P)Âàëþòà |C |9 |0
F=SP6682 |(P)Ïðîöåíò |N |5 |2
F=SP327 |(P)ÒèïÖåí |C |9 |0
#==TABLE no 24 : Ñïðàâî÷íèê Íîìåíêëàòóðà
# Name |Descr |SQLTableNam|RecordLock
T=SC84 |Ñïðàâî÷íèê Íîìåíêëàòóðà |SC84 |R
# ----Columns-------
# Name |Descr |Type|Length|Precision
F=ROW_ID |Row ID |I |0 |0
F=ID |ID object |C |9 |0
F=PARENTID |ID parent obj |C |9 |0
F=CODE |object code |C |8 |0
F=DESCR |object description |C |70 |0
F=ISFOLDER |Is Line - Folder |Y |0 |0
F=ISMARK |Object is Marked for|L |0 |0
F=VERSTAMP |Version stamp |I |0 |0
F=SP85 |(P)Àðòèêóë |C |25 |0
F=SP86 |(P)ÁàçîâàÿÅäèíèöà |C |9 |0
F=SP208 |(P)Âåñîâîé |N |1 |0
F=SP2417 |(P)ÂèäÍîìåíêëàòóðû |C |9 |0
F=SP97 |(P)ÌèíÎñòàòîê |N |13 |3
F=SP5066 |(P)ÍåÂêëþ÷àòüÂïðàéñ |N |1 |0
F=SP5013 |(P)ÍîìåðÃÒÄ |C |9 |0
F=SP94 |(P)ÎñíîâíàÿÅäèíèöà |C |9 |0
F=SP4427 |(P)ÎñíîâíîåÑâîéñòâî |C |9 |0
F=SP103 |(P)ÑòàâêàÍÄÑ |C |9 |0
F=SP104 |(P)ÑòàâêàÍÏ |C |9 |0
F=SP5012 |(P)ÑòðàíàÏðîèñõîæäåí|C |9 |0
F=SP8574 |(P)ÍèçÎòêëîíåíèÿÑåáå|N |4 |2
F=SP8575 |(P)ÂåðõÎòêëîíåíèÿÑåá|N |4 |2
F=SP8576 |(P)ÍèçÎòêëîíåíèÿÑïåö|N |4 |2
F=SP8577 |(P)ÂåðõÎòêëîíåíèÿÑïå|N |4 |2
F=SP8578 |(P)ÍèçÎòêëîíåíèÿÇàêó|N |4 |2
F=SP8579 |(P)ÂåðõÎòêëîíåíèÿÇàê|N |4 |2
F=SP8580 |(P)ÍèçÎòêëîíåíèÿÐîçí|N |4 |2
F=SP8581 |(P)ÂåðõÎòêëîíåíèÿÐîç|N |4 |2
F=SP8599 |(P)Äëèíà |N |6 |2
F=SP8600 |(P)Øèðèíà |N |6 |2
F=SP8601 |(P)Âûñîòà |N |6 |2
F=SP8602 |(P)Îáúåì |N |14 |5
F=SP8606 |(P)ÌàêñèìàëüíûéÏðîöå|N |4 |2
F=SP8607 |(P)Àäðåñ |C |9 |0
F=SP95 |(P)Êîììåíòàðèé |M |0 |0
F=SP101 |(P)ÏîëíÍàèìåíîâàíèå |M |0 |0
select * from (
select *, ROW_NUMBER() over(partition by nom.id,pt.id order by c.date desc) NUM
from sc84 as nom
join sc319 as p
on p.PARENTEXT = nom.id
join sc219 as pt
on p.sp327 = pt.id
join _1SCONST as c
on c.objid=p.id
) A
where NUM=1

Oracle: Recursively self referential join with nth level record

I have self referential table like this:
id |level | parent_id
----------------------
1 |1 |null
2 |1 |null
3 |2 |1
4 |2 |1
5 |2 |2
6 |3 |5
7 |3 |3
8 |4 |7
9 |4 |6
------------------------
I need nth level parent in result. for example 2nd level parent
id |level | parent_id| second_level_parent_id
------------------------------------------------
1 |1 |null |null
2 |1 |null |null
3 |2 |1 |null
4 |2 |1 |null
5 |2 |2 |null
6 |3 |5 |5
7 |3 |3 |3
8 |4 |7 |3
9 |4 |6 |5
-------------------------------------------------
this works for me.
SELECT m.*,
CONNECT_BY_ROOT id AS second_level_parent_id
FROM my_table m
WHERE CONNECT_BY_ROOT level =2
CONNECT BY prior id = parent_id;
thanks #Jozef Dúc

SQL: Need to SUM column for each type

How can I find the SUM of all scores for the minimum date of each lesson_id please:
-----------------------------------------------------------
|id |uid |group_id |lesson_id |game_id |score |date |
-----------------------------------------------------------
|1 |145 |1 |1 |0 |40 |1391627323 |
|2 |145 |1 |1 |0 |80 |1391627567 |
|3 |145 |1 |2 |0 |40 |1391627323 |
|4 |145 |1 |3 |0 |30 |1391627323 |
|5 |145 |1 |3 |0 |90 |1391627567 |
|6 |145 |1 |4 |0 |20 |1391628000 |
|7 |145 |1 |5 |0 |35 |1391628000 |
-----------------------------------------------------------
I need output:
-------------------
|sum_first_scores |
-------------------
|165 |
-------------------
I have this so far, which lists the score for each minimum date, per lesson, but I need to sum those results as above:
SELECT lesson_id, MIN(date), score AS first_score FROM cdu_user_progress
WHERE cdu_user_progress.uid = 145
GROUP BY lesson_id
You can identify the first score as the one where no earlier record exists. Then just take the sum:
select sum(score)
from edu_user_progress eup
where cdu_user_progress.uid = 145 and
not exists (select 1
from edu_user_progress eup2
where eup2.uid = eup.uid and
eup2.lesson_id = eup.lesson_id and
eup2.date < eup.date
);
This assumes that the minimum date for the lesson id has only one score.

SQL - get rows where column is greater than certain amount

I need to get the sum of the scores for the first of each lesson_id, but I also need the overall min and max scores for all lesson_ids as well as some other info:
cdu_groups:
----------------
|id |name |
----------------
|1 |group_1 |
|2 |group_2 |
----------------
cdu_user_progress145:
-----------------------------------------------------------
|id |uid |group_id |lesson_id |game_id |score |date |
-----------------------------------------------------------
|1 |145 |1 |1 |0 |40 |1391627323 |
|2 |145 |1 |1 |0 |80 |1391627567 |
|3 |145 |1 |2 |0 |40 |1391627323 |
|4 |145 |1 |3 |0 |30 |1391627323 |
|5 |145 |1 |3 |0 |90 |1391627567 |
|6 |145 |1 |4 |0 |20 |1391627323 |
|7 |145 |1 |5 |0 |35 |1391627323 |
-----------------------------------------------------------
I need this output:
-----------------------------------------------------------------
|name |group_id |min_score |max_score |... |sum_first_scores |
-----------------------------------------------------------------
|group_1 |1 |20 |90 |... |165 |
-----------------------------------------------------------------
SELECT
cdu_groups.*,
MAX(score) AS max_score,
MIN(score) AS min_score,
COUNT(DISTINCT(lesson_id)) AS scored_lesson_count,
COUNT(DISTINCT CASE WHEN score >= 75 then lesson_Id ELSE NULL END) as passed_lesson_count,
SUM(first_scores.first_score) AS sum_first_scores
FROM cdu_user_progress
JOIN cdu_groups ON cdu_groups.id = cdu_user_progress.group_id
JOIN
(
SELECT lesson_id, MIN(date), score AS first_score FROM cdu_user_progress
WHERE cdu_user_progress.uid = 145
GROUP BY lesson_id
) AS first_scores ON first_scores.lesson_id = cdu_user_progress.lesson_id
WHERE cdu_user_progress.uid = 145
I'm getting this error though:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUM(first_scores.first_score) AS sum_first_scores FROM cdu_user_progress ' at line 7