SQL Split String to letters each one in row - sql

I have case to get String from table , Split it to letters , each letter represent "active/inactive" "0/1" , then return description from other table for just all active letter IN ONE CELL ..
NOTE: Letters order as it is in other table ..
this is my case :
CREATE TABLE Strings_tab
(
Str_id NUMBER,
Str_text VARCHAR2 (40)
);
CREATE TABLE Reprsnt_Tab
(
rep_id NUMBER,
rep_text VARCHAR2 (40)
);
INSERT INTO Strings_tab VALUES (1, '1111111111000000000011111111110000000000');
INSERT INTO Strings_tab VALUES (2, '0000011111000001111100000111110000011111');
INSERT INTO Reprsnt_Tab VALUES (1, 'rep1');
INSERT INTO Reprsnt_Tab VALUES (2, 'rep2');
INSERT INTO Reprsnt_Tab VALUES (3, 'rep3');
INSERT INTO Reprsnt_Tab VALUES (4, 'rep4');
INSERT INTO Reprsnt_Tab VALUES (5, 'rep5');
INSERT INTO Reprsnt_Tab VALUES (6, 'rep6');
INSERT INTO Reprsnt_Tab VALUES (7, 'rep7');
INSERT INTO Reprsnt_Tab VALUES (8, 'rep8');
INSERT INTO Reprsnt_Tab VALUES (9, 'rep9');
INSERT INTO Reprsnt_Tab VALUES (10, 'rep10');
INSERT INTO Reprsnt_Tab VALUES (11, 'rep11');
INSERT INTO Reprsnt_Tab VALUES (12, 'rep12');
INSERT INTO Reprsnt_Tab VALUES (13, 'rep13');
INSERT INTO Reprsnt_Tab VALUES (14, 'rep14');
INSERT INTO Reprsnt_Tab VALUES (15, 'rep15');
INSERT INTO Reprsnt_Tab VALUES (16, 'rep16');
INSERT INTO Reprsnt_Tab VALUES (17, 'rep17');
INSERT INTO Reprsnt_Tab VALUES (18, 'rep18');
INSERT INTO Reprsnt_Tab VALUES (19, 'rep19');
INSERT INTO Reprsnt_Tab VALUES (20, 'rep20');
INSERT INTO Reprsnt_Tab VALUES (21, 'rep21');
INSERT INTO Reprsnt_Tab VALUES (22, 'rep22');
INSERT INTO Reprsnt_Tab VALUES (23, 'rep23');
INSERT INTO Reprsnt_Tab VALUES (24, 'rep24');
INSERT INTO Reprsnt_Tab VALUES (25, 'rep25');
INSERT INTO Reprsnt_Tab VALUES (26, 'rep26');
INSERT INTO Reprsnt_Tab VALUES (27, 'rep27');
INSERT INTO Reprsnt_Tab VALUES (28, 'rep28');
INSERT INTO Reprsnt_Tab VALUES (29, 'rep29');
INSERT INTO Reprsnt_Tab VALUES (30, 'rep30');
INSERT INTO Reprsnt_Tab VALUES (31, 'rep31');
INSERT INTO Reprsnt_Tab VALUES (32, 'rep32');
INSERT INTO Reprsnt_Tab VALUES (33, 'rep33');
INSERT INTO Reprsnt_Tab VALUES (34, 'rep34');
INSERT INTO Reprsnt_Tab VALUES (35, 'rep35');
INSERT INTO Reprsnt_Tab VALUES (36, 'rep36');
INSERT INTO Reprsnt_Tab VALUES (37, 'rep37');
INSERT INTO Reprsnt_Tab VALUES (38, 'rep38');
INSERT INTO Reprsnt_Tab VALUES (39, 'rep39');
INSERT INTO Reprsnt_Tab VALUES (40, 'rep40');
COMMIT;
this is my query :
SELECT STR_TEXT,
RTRIM (
XMLAGG (XMLELEMENT (E, DATA.REP_TEXT || ',' || CHR (10))).EXTRACT (
'//text()'),
',')
REPS
FROM ( SELECT LETTER,
STR_ID,
LVL,
STR_TEXT,
REP_TEXT
FROM ( SELECT DISTINCT SUBSTR (A.STR_TEXT, LEVEL, 1) LETTER,
A.STR_ID,
LEVEL LVL,
A.STR_TEXT
FROM STRINGS_TAB A
CONNECT BY LEVEL <= LENGTH (A.STR_TEXT) ---- HERE IS MY PROBLEM
) TXT,
( SELECT ROWNUM RN, REPRSNT_TAB.*
FROM REPRSNT_TAB
ORDER BY REP_ID) B
WHERE B.RN = TXT.LVL AND LETTER = 1
ORDER BY STR_ID, STR_TEXT, LVL) DATA
GROUP BY STR_TEXT
This query get correct data
If i put like 10 in place of "LENGTH (A.STR_TEXT)" to get first 10 letters of each string.
BUT .. If "LENGTH (A.STR_TEXT)" was so big , in my case 40 , the query will hang
so, please , advice me .. in this case ???
RESULT from my Query , IF I put "LEVEL <= 10" :
STR_TEXT REP
------------------------------- ------------------------------
000001111100000111110000011111 rep6,rep10,rep9,rep8,rep7
111111111100000000001111111111 rep1,rep10,rep9,rep8,rep7,rep6,rep5,rep4,rep3,rep2

My approach takes the CONNECT BY to an auxiliary table (using CONNECT BY LEVEL in a table with more than 1 row is not a good idea IMHO. Look here) :
with aux as (select level as lvl
from dual
connect by level <= (select max(length(str_text)) from strings_tab))
SELECT STR_TEXT,
RTRIM (
XMLAGG (XMLELEMENT (E, DATA.REP_TEXT || ',' || CHR (10))).EXTRACT (
'//text()'),
',')
REPS
FROM ( SELECT LETTER,
STR_ID,
LVL,
STR_TEXT,
REP_TEXT
FROM ( SELECT DISTINCT SUBSTR (A.STR_TEXT, LVL, 1) LETTER,
A.STR_ID,
LVL,
A.STR_TEXT
FROM STRINGS_TAB A join aux x on x.lvl <=LENGTH (A.STR_TEXT)
) TXT,
( SELECT ROWNUM RN, REPRSNT_TAB.*
FROM REPRSNT_TAB
ORDER BY REP_ID) B
WHERE B.RN = TXT.LVL AND LETTER = 1
ORDER BY STR_ID, STR_TEXT, LVL) DATA
GROUP BY STR_TEXT;
OUTPUT (WITHOUT (CHAR(10))
STR_TEXT REPS
0000011111000001111100000111110000011111 rep6,rep40,rep39,rep38,rep37,rep36,rep30,rep29,rep28,rep27,rep26,rep20,rep19,rep18,rep17,rep16,rep10,rep9,rep8,rep7
1111111111000000000011111111110000000000 rep1,rep30,rep29,rep28,rep27,rep26,rep25,rep24,rep23,rep22,rep21,rep10,rep9,rep8,rep7,rep6,rep5,rep4,rep3,rep2

This is My Answer :
SELECT str_text,
LISTAGG (DATA.REP_TEXT, ',' || CHR (10))
WITHIN GROUP (ORDER BY DATA.rn_rep)
reps
FROM (SELECT *
FROM ( SELECT str_text, SUBSTR (str_text, rn, 1) OneDigit, rn
FROM (SELECT str_text FROM STRINGS_TAB) txt,
( SELECT ROWNUM rn
FROM DUAL
CONNECT BY LEVEL <=
(SELECT MAX (LENGTH (str_text))
FROM STRINGS_TAB)) rep
WHERE REP.RN <= LENGTH(str_text)
ORDER BY Str_text, rn) xx,
( SELECT ROWNUM rn_rep, rep_text
FROM REPRSNT_TAB
ORDER BY rn_rep) desc_rep
WHERE desc_rep.rn_rep = xx.rn AND OneDigit = 1) data
GROUP BY str_text

select Str_id
,Str_text
,xmlquery('let $abc := for $i in 1 to string-length($str)
where substring($str, $i, 1) = "1"
return $data/rows/row[$i]/text()
return string-join( $abc, ",")'
passing Str_text as "str"
, (select xmlelement("rows",xmlagg(xmlelement( "row",rep_text) order by rep_id)) from Reprsnt_Tab) as "data"
returning content
) from Strings_tab
The table Reprsnt_Tab is aggregate to one xmlelemtnt. To access selected row you have to just do $doc/rows/row[$selected_row_nr]/text()

Related

Find the Biggest Number of Consecutive Occurrence of values in Table

I have the following table
create table Launches (Id int, Name char)
insert into Launches values
(1, 'A'),
(2, 'A'),
(3, 'B'),
(4, 'B'),
(5, 'B'),
(6, 'B'),
(7, 'C'),
(8, 'B'),
(9, 'B')
The result should be
4 - B
From 3 to 6
Similar question -
Count Number of Consecutive Occurrence of values in Table
You can subtract an enumerated value for each name to get a constant for adjacent values that are the same. The rest is aggregation:
select top (1) name, count(*), min(id), max(id)
from (select l.*,
row_number() over (partition by name order by id) as seqnum
from #Launches l
) l
group by (id - seqnum), name
order by count(*) desc;
Here is a db<>fiddle.

Can I improve this query for use in large tables?

How can I improve this query for use in large tables....?
I use a table ('DataValues') to store a collection of values ('Value') for collections ('Visit_id') ie it records certain values for each visit.
I use a table ('MatchItems') to store dynamic match sets 'MatchSet' of values ('Value'), sets can contain any number of values. The table also has a IsNeg field to indicate if the match should require a value to be not present in the visit collection.
This allows me to dynamically match visits that conform to certain criteria such as
Must contain values A, B and C and NOT D OR C and B AND NOT A.
ie (Value = A and Value = B and Value = C and Value /= D)
or (Value = C and Value = B and Value /= A)
I have a query that delivers a reasonable solution fiddle:
CREATE TABLE DataValues (
id NUMBER(5) CONSTRAINT DataValues_pk PRIMARY KEY,
Visit_id Number(5) ,
Value varchar(5)
);
INSERT INTO DataValues VALUES (1, 1, 'M');
INSERT INTO DataValues VALUES (2, 1, 'I');
INSERT INTO DataValues VALUES (3, 1, 'C');
INSERT INTO DataValues VALUES (4, 1, 'K');
INSERT INTO DataValues VALUES (5, 1, 'E');
INSERT INTO DataValues VALUES (6, 1, 'Y');
INSERT INTO DataValues VALUES (7, 2, 'M');
INSERT INTO DataValues VALUES (8, 2, 'O');
INSERT INTO DataValues VALUES (9, 2, 'U');
INSERT INTO DataValues VALUES (10, 2, 'S');
INSERT INTO DataValues VALUES (11, 2, 'E');
INSERT INTO DataValues VALUES (12, 3, 'C');
INSERT INTO DataValues VALUES (13, 3, 'A');
INSERT INTO DataValues VALUES (14, 3, 'T');
INSERT INTO DataValues VALUES (15, 4, 'S');
INSERT INTO DataValues VALUES (16, 4, 'A');
INSERT INTO DataValues VALUES (17, 4, 'T');
INSERT INTO DataValues VALUES (18, 5, 'M');
INSERT INTO DataValues VALUES (19, 5, 'A');
INSERT INTO DataValues VALUES (20, 5, 'T');
CREATE TABLE MatchItems (
id NUMBER(5) CONSTRAINT MatchItems_pk PRIMARY KEY,
MatchSet Number(5),
Value VARCHAR(5),
IsNeg NUMBER(1) NOT NULL CHECK (IsNeg in (0,1))
);
INSERT INTO MatchItems VALUES (1, 1, 'M', 0);
INSERT INTO MatchItems VALUES (2, 1, 'I', 0);
INSERT INTO MatchItems VALUES (3, 1, 'C', 0);
INSERT INTO MatchItems VALUES (4, 1, 'K', 0);
INSERT INTO MatchItems VALUES (5, 1, 'E', 0);
INSERT INTO MatchItems VALUES (6, 1, 'Y', 0);
INSERT INTO MatchItems VALUES (7, 2, 'C', 0);
INSERT INTO MatchItems VALUES (8, 2, 'A', 0);
INSERT INTO MatchItems VALUES (9, 3, 'A', 0);
INSERT INTO MatchItems VALUES (10, 3, 'T', 0);
INSERT INTO MatchItems VALUES (11, 4, 'S', 1);
INSERT INTO MatchItems VALUES (12, 4, 'A', 0);
INSERT INTO MatchItems VALUES (13, 4, 'K', 1);
INSERT INTO MatchItems VALUES (14, 5, 'A', 0);
INSERT INTO MatchItems VALUES (15, 5, 'T', 0);
SELECT
MatchItems.MatchSet,
DataValues.Visit_id,
GpMatchItems.Count TgtCount,
Count(MatchItems.Id),
sum(MatchItems.IsNeg)
FROM DataValues
LEFT JOIN MatchItems ON MatchItems.Value = DataValues.Value
--AND MatchItems.MatchSet = 4
LEFT JOIN (SELECT
MatchItems.MatchSet,
count(*) Count
FROM MatchItems
WHERE
MatchItems.IsNeg = 0
GROUP BY
MatchItems.MatchSet) GpMatchItems ON GpMatchItems.MatchSet = MatchItems.MatchSet
HAVING
Count(MatchItems.Id) = GpMatchItems.Count
AND sum(MatchItems.IsNeg) = 0
GROUP BY
MatchItems.MatchSet,
DataValues.Visit_id,
GpMatchItems.Count
How can I improve the performance of this query where the DataValues table contains 100m records, and MatchItems may include a collection of 50 sets each of 2 - 20 values?
You can try this version using Analytic functions and see if it performs any better. This query removes the subquery GpMatchItems that you are joining with.
SELECT DISTINCT matchset,
visit_id,
tgtcount,
match_visit_count,
isneg_sum
FROM (SELECT MatchItems.MatchSet,
DataValues.Visit_id,
COUNT (DISTINCT CASE MatchItems.IsNeg WHEN 0 THEN MatchItems.id ELSE NULL END)
OVER (PARTITION BY MatchItems.MatchSet)
AS tgtcount,
COUNT (*) OVER (PARTITION BY MatchItems.MatchSet, DataValues.Visit_id)
AS match_visit_count,
SUM (MatchItems.IsNeg) OVER (PARTITION BY MatchItems.MatchSet, DataValues.Visit_id)
AS isneg_sum
FROM DataValues LEFT JOIN MatchItems ON MatchItems.VALUE = DataValues.VALUE)
WHERE tgtcount = match_visit_count AND isneg_sum = 0;
I have adjusted EJ's suggestion to include a LEFT JOIN to collect the tgtCount to identify the total number of good matches required in each MatchSet:
SELECT DISTINCT matchset,
visit_id,
tgtcount,
match_visit_count,
isneg_sum
GpMatchItems.count tgtCount
FROM
COUNT (*) OVER (PARTITION BY MatchItems.MatchSet, DataValues.Visit_id)
AS match_visit_count,
SUM (MatchItems.IsNeg) OVER (PARTITION BY MatchItems.MatchSet, DataValues.Visit_id)
AS isneg_sum
FROM DataValues
LEFT JOIN MatchItems ON MatchItems.VALUE = DataValues.VALUE)
LEFT JOIN ( SELECT
MatchItems.MatchSet,
count(*) Count
FROM MatchItems
WHERE MatchItems.IsNeg = 0
GROUP BY
MatchItems.MatchSet) GpMatchItems
ON GpMatchItems.MatchSet = MatchItems.MatchSet
)
WHERE
tgtcount = match_visit_count
AND isneg_sum = 0;

Outer Joins with Multiple Conditions in Oracle Join Syntax

I have the tables below
create table xx_base_tbl
(
tbl_id number
, trx_num varchar2(100)
);
create table xx_dtl_tbl
(
dtl_id number
, tbl_id number
, category varchar2(100)
, attribute1 varchar2(100)
);
insert into xx_base_tbl (tbl_id, trx_num) values (1, 'trx 1');
insert into xx_base_tbl (tbl_id, trx_num) values (2, 'trx 2');
insert into xx_base_tbl (tbl_id, trx_num) values (3, 'trx 3');
insert into xx_base_tbl (tbl_id, trx_num) values (4, 'trx 4');
insert into xx_base_tbl (tbl_id, trx_num) values (5, 'trx 5');
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (1, 1, null, 'SAMPLE');
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (2, 1, null, 'hello');
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (3, 2, 'PREPAYMENT', 'this is not a value');
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (4, 2, 'PREPAYMENT', 1);
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (5, 3, 'PREPAYMENT', 2);
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (6, 3, 'PREPAYMENT', 1);
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (7, 3, 'SAMPLE', 15678);
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (8, 4, 'PREPAYMENT', 1);
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (9, 4, 'PREPAYMENT', NULL);
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (10, 5, 'PREPAYMENT', null);
insert into xx_dtl_tbl (dtl_id, tbl_id, category, attribute1) values (11, 5, 'SAMPLE', 'YEY');
I am using the ANSI Syntax below to outer join xx_dtl_tbl to another xx_base_tbl show only CATEGORY with PREPAYMENT and numeric values only. then use LISTAGG() to aggregate the results into a single row
SELECT
xx1.trx_num,
LISTAGG(xx3.trx_num, ',') WITHIN GROUP(
ORDER BY
xx3.trx_num
) prepayment
FROM
xx_base_tbl xx1
INNER JOIN xx_dtl_tbl xx2 ON xx1.tbl_id = xx2.tbl_id
LEFT JOIN xx_base_tbl xx3 ON (to_number(xx2.attribute1) = xx3.tbl_id and length(TRIM(translate(xx2.attribute1, ' +-.0123456789', ' '))) IS NULL)
GROUP BY
xx1.trx_num
The result looks fine:
TRX_NUM PREPAYMENT
------- -------------
trx 1
trx 2 trx 1
trx 3 trx 1,trx 2
trx 4 trx 1
trx 5
However, when i use SQL Developer's tool to change the syntax to Oracle Join Syntax, it get the below result:
SELECT
xx1.trx_num,
LISTAGG(xx3.trx_num, ',') WITHIN GROUP(
ORDER BY
xx3.trx_num
) prepayment
FROM
xx_base_tbl xx1,
xx_dtl_tbl xx2,
xx_base_tbl xx3
WHERE
xx1.tbl_id = xx2.tbl_id
AND to_number(xx2.attribute1) = xx3.tbl_id (+)
AND ( length(TRIM(translate(xx2.attribute1, ' +-.0123456789', ' '))) IS NULL )
GROUP BY
xx1.trx_num
The result changed:
TRX_NUM PREPAYMENT
------- -------------
trx 2 trx 1
trx 3 trx 1,trx 2
trx 4 trx 1
trx 5
the trx 1 row is suddenly missing. How can I write this in Oracle Syntax?
This query is not so easy to transform to old syntax. Something which worked for me is:
select a.trx_num,
listagg(b.trx_num, ',') within group (order by b.trx_num) prepayment
from (
select trx_num, attribute1,
case when trim(translate(xx2.attribute1, ' +-.0123456789', ' ')) is null
then to_number(xx2.attribute1)
end attr_num
from xx_base_tbl xx1, xx_dtl_tbl xx2
where xx1.tbl_id = xx2.tbl_id) a,
xx_base_tbl b
where a.attr_num = b.tbl_id (+)
group by a.trx_num
dbfiddle
Two steps, in first create joining column using case when in subquery, then use it in main query.
Edit:
Above query may be simplified to:
select xx1.trx_num,
listagg(xx3.trx_num, ',') within group (order by xx3.trx_num) prepayment
from xx_base_tbl xx1, xx_dtl_tbl xx2, xx_base_tbl xx3
where xx1.tbl_id = xx2.tbl_id
and case when trim(translate(xx2.attribute1, ' +-.0123456789', ' ')) is null
then to_number(xx2.attribute1)
end = xx3.tbl_id(+)
group by xx1.trx_num
dbfiddle
The syntax that is used in your first query is ANSI standard joins and properly works with oracle.
Second query's syntax is old SQL-92 standard and should be avoided. Also, it is hard to understand and handle.
By the way, your second query will need some extra clauses as follows:
WHERE
xx1.tbl_id = xx2.tbl_id
AND to_number(xx2.attribute1) = xx3.tbl_id (+)
AND (xx3.tbl_id is null -- this extra OR condition is needed with below condition
or ( length(TRIM(translate(xx2.attribute1, ' +-.0123456789', ' '))) IS NULL )
)

SQL query for searching in the tree

I have a simple tree that has 4 level of deep data. Here is the table DDL
CREATE TABLE HIER_DEMO(
ID NUMBER,
LABEL VARCHAR2 (100),
PARENT_ID NUMBER)
Hierarchy starts WITH ID = PARENT_ID. Number of levels are fixed. It is always 4. We have leafs to all branches at 4th level. So we can also add 3 more columns that represent LABEL of ancestors if necessary.
I need to build a query that
Searches for particular phrase in LABEL on any level of hierarchy. For example LABEL LIKE '%MAGIC_WORD%'.
Returns all the nodes till leaf level under the hierarchy node that satisfies condition 1.
In addition we need to return all the ancestors of the hierarchy node that satisfies condition 1.
Here is an example
INSERT INTO HIER_DEMO VALUES (1, 'Mike', 1);
INSERT INTO HIER_DEMO VALUES (2, 'Arthur', 2);
INSERT INTO HIER_DEMO VALUES (3, 'Alex', 1);
INSERT INTO HIER_DEMO VALUES (4, 'Suzanne', 1);
INSERT INTO HIER_DEMO VALUES (5, 'Brian', 3);
INSERT INTO HIER_DEMO VALUES (6, 'Rick', 3);
INSERT INTO HIER_DEMO VALUES (7, 'Patrick', 4);
INSERT INTO HIER_DEMO VALUES (8, 'Simone', 4);
INSERT INTO HIER_DEMO VALUES (9, 'Tim', 5);
INSERT INTO HIER_DEMO VALUES (10, 'Andrew', 5);
INSERT INTO HIER_DEMO VALUES (11, 'Sandy', 6);
INSERT INTO HIER_DEMO VALUES (12, 'Brian', 6);
INSERT INTO HIER_DEMO VALUES (13, 'Chris', 7);
INSERT INTO HIER_DEMO VALUES (14, 'Laure', 7);
INSERT INTO HIER_DEMO VALUES (15, 'Maureen', 8);
INSERT INTO HIER_DEMO VALUES (16, 'Andy', 8);
INSERT INTO HIER_DEMO VALUES (17, 'Al', 2);
INSERT INTO HIER_DEMO VALUES (18, 'John', 17);
INSERT INTO HIER_DEMO VALUES (19, 'Frank', 18);
INSERT INTO HIER_DEMO VALUES (20, 'Tim', 19);
I am looking for the query that searches the tree for word 'Brian' in the LABEL column
The query should return these data
ID LABEL PARENT_ID
1 Mike 1
3 Alex 1
5 Brian 3
6 Rick 3
9 Tim 5
10 Andrew 5
12 Brian 6
Could somebody help with the Oracle query? We are using 11.2 version of Oracle database.
SQL> select * from HIER_DEMO
2 start with label like '%Brian%'
3 connect by prior id = parent_id
4 union
5 select * from HIER_DEMO
6 start with label like '%Brian%'
7 connect by prior parent_id = id and PRIOR parent_id != PRIOR id
8 /
ID LABEL PARENT_ID
---- -------------------- ---------
1 Mike 1
3 Alex 1
5 Brian 3
6 Rick 3
9 Tim 5
10 Andrew 5
12 Brian 6
We can use recursive CTE to accomplish this
WITH CTE1(ID, LABEL,PARENT_ID) AS
(
SELECT * FROM Hier_Demo
WHERE LABEL LIKE '%Brian%'
UNION ALL
SELECT h.ID, h.LABEL, h.PARENT_ID FROM Hier_Demo h
INNER JOIN CTE1 c
ON h.ID = c.PARENT_ID
WHERE h.ID <> h.PARENT_ID
),
CTE2(ID, LABEL,PARENT_ID) AS
(
SELECT * FROM Hier_Demo
WHERE LABEL LIKE '%Brian%'
UNION ALL
SELECT h.ID, h.LABEL, h.PARENT_ID FROM Hier_Demo h
INNER JOIN CTE2 c
ON h.PARENT_ID = c.ID
)
SELECT * FROM CTE2
UNION
SELECT * FROM CTE1
UNION
SELECT * FROM HIER_DEMO WHERE ID = 1
In the above code CTE1 gets records up in the hierarchy and CTE2 gets records down in the hierarchy of Brian, after that we just UNION the records returned by these CTEs
see the code working at SQLFiddle: http://sqlfiddle.com/#!4/0c99d/39
You can try this :
SELECT * FROM HIER_DEMO WHERE PARENT_ID=
(SELECT id FROM HIER_DEMO WHERE LABEL='Brian');

SQL Query count

HI there I have this table,
Recipe = (idR, recipeTitle, prepText, cuisineType, mealType)
Ingredient = (idI, ingrDesc)
RecipIngr = (idR*, idI*)
and I'm trying to query a list for ingrDesc with a count of how many recipies that ingrDesc is in. I want to list only those ingrDesc that occur more than 10 times.
Here's what I have:
SELECT a.idI, a.recipeTitle
FROM Recipe a
INNER JOIN recpingr b
ON a.idr = b.idr
WHERE a.preptext = '>10'
Any help as I don't know how to carry on with this query
Use GROUP BY with HAVING:
SELECT i.idI, i.ingrDesc, COUNT(*)
FROM Ingredient i
INNER JOIN RecipIngr ri ON i.idI = ri.idI
GROUP BY i.idI, i.ingrDesc
HAVING COUNT(*) > 10
You need to use a group by clause and having. I have created a quick sample here but my sample data does not go up to 10 so I used any ingredient that was used more than once (> 1).
Here is the sample data:
create table dbo.recipe (
idR int not null,
recipeTitle varchar(100) not null,
prepText varchar(4000) null,
cuisineType varchar(100) null,
mealType varchar(100) null
)
go
insert into dbo.recipe values (1, 'Eggs and Bacon', 'Prep Text 1', 'American', 'Breakfast')
insert into dbo.recipe values (2, 'Turkey Sandwich', 'Prep Text 2', 'American', 'Lunch')
insert into dbo.recipe values (3, 'Roast Beef Sandwich', 'Prep Text 3', 'American', 'Lunch')
go
create table dbo.ingredient (
idI int not null,
ingrDesc varchar(200) not null
)
go
insert into dbo.ingredient values (1, 'Large Egg')
insert into dbo.ingredient values (2, 'Bacon');
insert into dbo.ingredient values (3, 'Butter');
insert into dbo.ingredient values (4, 'Sliced Turkey');
insert into dbo.ingredient values (5, 'Lettuce');
insert into dbo.ingredient values (6, 'Tomato');
insert into dbo.ingredient values (7, 'Onion');
insert into dbo.ingredient values (8, 'Bread');
insert into dbo.ingredient values (9, 'Mustard');
insert into dbo.ingredient values (10, 'Horseradish');
insert into dbo.ingredient values (11, 'Sliced Roast Beef');
go
create table dbo.recipingr(
idR int not null,
idI int not null
)
go
insert into dbo.recipingr values (1, 1);
insert into dbo.recipingr values (1, 2);
insert into dbo.recipingr values (2, 4);
insert into dbo.recipingr values (2, 5);
insert into dbo.recipingr values (2, 6);
insert into dbo.recipingr values (2, 7);
insert into dbo.recipingr values (2, 8);
insert into dbo.recipingr values (2, 9);
insert into dbo.recipingr values (3, 11);
insert into dbo.recipingr values (3, 10);
insert into dbo.recipingr values (3, 8);
insert into dbo.recipingr values (3, 6);
insert into dbo.recipingr values (3, 5);
go
Here is the query:
select
i.ingrDesc,
count(*) ingrCount
from
dbo.recipe r
inner join dbo.recipingr ri on ri.idR = r.idR
inner join dbo.ingredient i on i.idI = ri.idI
group by
i.ingrDesc
having
count(*) > 1