How to use sum and joins within group_concat - sqlite

I have two tables, CustomerCategories and Articles. Both tables have a column called VatPercentage and VatPrice.
Scenarios:
In case of same vatpercentage exists in both tables i want to sum the vatprice from both tables and add it to the string.
In case of vatpercentage only exists in CustomerCategories table i want to sum the vatprice from here and add it to the string.
In case of vatpercentage only exists in Articles table i want to sum the vatprice from here and add it to the string.
Example tables:
Articles:
ArticleId TotalPrice VatPercentage VatPrice
1 100 25.0000000000 25
2 80 25.0000000000 20
3 50 8.0000000000 4
4 70 8.0000000000 5.6
5 20 0 0
6 0 0 0
CustomerCategories:
CustomerCategoryId TotalPrice VatPercentage VatPrice
2 163 8.0000000000 13
2 163 13.0000000000 13
2 163 0 0
2 150 25.0000000000 37.5
The result i want back from the Query in this case:
{esc}{40h}25 %{esc}{41h}82.5 NOK{lf}{esc}{40h}8 %{esc}{41h}22.6 NOK{lf}{esc}{40h}13 %{esc}{41h}13 NOK{lf}
The code i've trying without any positive results is:
SELECT GROUP_CONCAT(Result, '|') Results
FROM (
select case when cc.VatPercentage = a.VatPercentage
then
SELECT '{esc}{40}' || CAST(cc.VatPercentage AS INTEGER) || '% ' ||
(SUM(cc.VatPrice) + SUM(a.VatPrice)) || ' NOK' || '{lf}' Result end
else
(
case when cc.VatPercentage <> a.VatPercentage
then
SELECT '{esc}{40}' || CAST(cc.VatPercentage AS INTEGER) || '% ' ||
(SUM(cc.VatPrice) + SUM(a.VatPrice)) || ' NOK' || '{lf}' ||
SELECT '{esc}{40}' || CAST(a.VatPercentage AS INTEGER) || '% ' ||
(SUM(a.VatPrice)) || ' NOK' || '{lf}' Result
end
)
FROM CustomerCategories cc
LEFT JOIN Articles a
on cc.VatPercentage = a.VatPercentage
WHERE
cc.VatPercentage != '0'
AND a.VatPercentage != '0'
AND cc.TotalPrice != '0'
AND a.TotalPrice != '0'
GROUP BY
cc.VatPercentage OR a.VatPercentage) x
Help would be appreciated.
Fiddle

First, combine both tables:
SELECT VatPercentage, VatPrice FROM CustomerCategories
UNION ALL
SELECT VatPercentage, VatPrice FROM Articles
VatPercentage VatPrice
8.0000000000 13
13.0000000000 13
0 0
25.0000000000 37.5
25.0000000000 25
25.0000000000 20
8.0000000000 4
8.0000000000 5.6
0 0
0 0
Then do a simple GROUP BY over that:
SELECT VatPercentage,
SUM(VatPrice) AS PriceSum
FROM (SELECT VatPercentage, VatPrice FROM CustomerCategories
UNION ALL
SELECT VatPercentage, VatPrice FROM Articles)
WHERE VatPercentage != '0'
GROUP BY VatPercentage
Then do the escape characters mess over the result of that:
SELECT GROUP_CONCAT('{esc}{40h}' || VatPercentage || ' %' ||
'{esc}{41h}' || VatPrice || ' NOK{lf}',
'')
FROM (SELECT VatPercentage,
SUM(VatPrice) AS PriceSum
FROM (SELECT VatPercentage, VatPrice FROM CustomerCategories
UNION ALL
SELECT VatPercentage, VatPrice FROM Articles)
WHERE VatPercentage != '0'
GROUP BY VatPercentage)

Related

SQLite convert single row to multiple rows

SQLite
I want to convert single row value seperate by ',' to multiple rows
Example :
Single_Row
6,7,8,9,10,11,12,13,14,15,16
Result must be :
MultipleRows
6
7
8
9
10
12
13
14
15
16
I tried doing it with substr function but getting unexpected result
select
numbers.n,
substr(CbahiHSSpecialtyUnits.units,numbers.n,1)
from
numbers inner join CbahiHSSpecialtyUnits
on LENGTH(CbahiHSSpecialtyUnits.units)
- LENGTH(REPLACE(CbahiHSSpecialtyUnits.units, ',', ''))>=numbers.n-1
WHERE HsSubStandardID=22 and SpecialtyID=2 and numbers.n>0
order by numbers.n;
One good thing is I'm getting number of rows correct.. But the values that should be separated is wrong ..
Please note numbers table is I have created for indexing purpose, with the help of this post.
SQL split values to multiple rows
You can do it with a recursive CTE:
WITH cte AS (
SELECT SUBSTR(Units, 1, INSTR(Units || ',', ',') - 1) col,
SUBSTR(Units, INSTR(Units || ',', ',') + 1) value
FROM CbahiHSSpecialtyUnits
WHERE HsSubStandardID=22 AND SpecialtyID = 2
UNION ALL
SELECT SUBSTR(value, 1, INSTR(value || ',', ',') - 1),
SUBSTR(value, INSTR(value || ',', ',') + 1)
FROM cte
WHERE LENGTH(value) > 0
)
SELECT col
FROM cte
WHERE col + 0 > 0
Or, if you know the upper limit of the numbers is, say 20 and there are no duplicates among the numbers:
WITH cte AS (SELECT 1 col UNION ALL SELECT col + 1 FROM cte WHERE col < 20)
SELECT c.col
FROM cte c INNER JOIN CbahiHSSpecialtyUnits u
ON ',' || u.Units || ',' LIKE '%,' || c.col || ',%'
WHERE HsSubStandardID=22 AND SpecialtyID = 2
See the demo.
Results:
col
6
7
8
9
10
11
12
13
14
15
16
I got the solution
http://www.samuelbosch.com/2018/02/split-into-rows-sqlite.html
WITH RECURSIVE split(predictorset_id, predictor_name, rest) AS (
SELECT CbahiHSSpecialtyUnits.SpclUnitSerial, '', units || ',' FROM CbahiHSSpecialtyUnits WHERE HsSubStandardID=22 and SpecialtyID=2
UNION ALL
SELECT predictorset_id,
substr(rest, 0, instr(rest, ',')),
substr(rest, instr(rest, ',')+1)
FROM split
WHERE rest <> ''

SQLite Question: How can i get in a Specific Row all datas which are not null?

Ok, It will be much clearer once if done a Example:
RowId Name ID1 ID2 ID3 ID4 ID5 ID6 ID7 ID8 ID9 ID10
1 Alex 11 22 0 0 0 0 14 44 0 0
2 John 0 23 0 0 44 0 33 88 0 77
Ok, i want to get following result:
Alex 11 22 14 44
So the first part of the Query is clear,
Select *
from Table
where Name = Alex AND *Now im not sure if i need to use IS NOT NULL or => 1*
The following will produce the required result :-
SELECT
Name ||' '||
CASE WHEN coalesce(id1,0) <> 0 THEN id1||' ' ELSE '' END
||CASE WHEN coalesce(id2,0) <> 0 THEN id2||' ' ELSE '' END
||CASE WHEN coalesce(id3,0) <> 0 THEN id3||' ' ELSE '' END
||CASE WHEN coalesce(id4,0) <> 0 THEN id4||' ' ELSE '' END
||CASE WHEN coalesce(id5,0) <> 0 THEN id5||' ' ELSE '' END
||CASE WHEN coalesce(id6,0) <> 0 THEN id6||' ' ELSE '' END
||CASE WHEN coalesce(id7,0) <> 0 THEN id7||' ' ELSE '' END
||CASE WHEN coalesce(id8,0) <> 0 THEN id8||' ' ELSE '' END
||CASE WHEN coalesce(id9,0) <> 0 THEN id9||' ' ELSE '' END
||CASE WHEN coalesce(id10,0) <> 0 THEN id10||' ' ELSE '' END
AS myidlist
FROM mytable
WHERE Name = 'Alex'
;
the coalesce function, as used,turns null into 0 simplyfying the condition check. An alternative would be to use CASE WHEN id1 <> 0 AND id1 IS NOT NULL THEN id1||' ' ELSE '' END
However, the result will possibly be of little use or complicated to manipulate as a result (e.g. where do the numeric values come from such as what does 22 mean other than it's one of the values stored in one of the ID? columns).
Alternative approach
This approach assumes that you have a variable number of values per name (this may not necessarily be what you want).
Consider the following that, rather than using numerous columns to store the values RELATED to a name (related highlighted as SQLite is a relational database), it stores those values in a related table using a one-to-many relationship (there are many values each is realted to 1 name).
This bit creates the alternative structure/schema i.e. 2 tables one for the parent data another for the child data (the parent can have 0- many children each being a value)
CREATE TABLE IF NOT EXISTS mytable2 (Name TEXT PRIMARY KEY);
CREATE TABLE IF NOT EXISTS mytable2_ids (
Name_reference TEXT
REFERENCES mytable2(Name) ON DELETE CASCADE ON UPDATE CASCADE -- optional Foreign Key
,
id INTEGER
);
This inserts the data equivalent to you original data.
INSERT INTO mytable2 VALUES('Alex'),('John');
INSERT INTO mytable2_ids VALUES
('Alex',11),('Alex',22),('Alex',14),('Alex',44)
, ('John',23),('John',44),('John',33),('John',88),('John',77)
;
This is the query that produces the same result :-
SELECT Name||group_concat(id,' ') AS myidlist FROM mytable2 JOIN mytable2_ids ON Name = Name_reference WHERE name = 'Alex';
group_concat is an aggregate function that concatenates all the values of a group of data. In this case the group is all of the data as there is no GROUP BY clause. So it takes ALL of the values in the id columnof the JOINED (related) mytable2_ids and concatenates them.
The result being :-

LISTAGG IN PL/SQL

Help please find mistake in creating function which will return one row from list.
SELECT listagg(' ' || V_RECEIVING_LIST.DOCUMENT_NUMBER || CHR(13))
WITHIN GROUP (ORDER BY V_RECEIVING_LIST.DOCUMENT_NUMBER)
FROM svc.claim_detail, tbc.v_receiving_list
WHERE claim_detail.id_claim = 334455
AND V_RECEIVING_LIST.ID_RECEIVING_LIST = CLAIM_DETAIL.ID_RECEIVING_LIST
The code return correct result.
But the next dont return the same.
DECLARE
scodes VARCHAR2 (4000);
BEGIN
SELECT (LISTAGG(' ' || RECEIVING_LIST.DOCUMENT_NUMBER || CHR(13))
WITHIN GROUP (ORDER BY RECEIVING_LIST.DOCUMENT_NUMBER))
INTO scodes
FROM svc.claim_detail, tbc.v_receiving_list
WHERE claim_detail.id_claim = 334455
AND RECEIVING_LIST.ID_RECEIVING_LIST = CLAIM_DETAIL.ID_RECEIVING_LIST;
DBMS_OUTPUT.PUT_LINE(scodes);
END;
SQL> select * from V_RECEIVING_LIST ;
DOCUMENT_NUMBER ID_RECEIVING_LIST
--------------- --------------------
1 a
1 a
2 b
SQL> select * from claim_detail ;
ID_CLAIM ID_RECEIVING_LIST
---------- --------------------
123 a
123 a
124 b
SQL> DECLARE
2 scodes VARCHAR2 (4000);
3 BEGIN
4 SELECT (LISTAGG(' '|| v_receiving_list.DOCUMENT_NUMBER || CHR(13))
5 WITHIN GROUP (ORDER BY v_receiving_list.DOCUMENT_NUMBER))
6
7 INTO scodes
8 FROM claim_detail, v_receiving_list
9 WHERE claim_detail.id_claim = 123
10 AND v_receiving_list.ID_RECEIVING_LIST = CLAIM_DETAIL.ID_RECEIVING_LIST;
11
12
13 DBMS_OUTPUT.PUT_LINE('The output is '||scodes);
14 END;
15 /
1e output is 1
PL/SQL procedure successfully completed.

Using of sum withinin group_concat

Let's say i have a table, Product. This contains several Products with different vatpercentages and vatprices:
Product
ArticleId | Price | VatPercentage | VatPrice
(integer) (numeric) (varchar) (numeric)
--------------------------------------------
1 100 25.0000000000 25
2 80 25.0000000000 20
3 50 8.0000000000 4
4 70 8.0000000000 5.6
5 20 0 0
0
Now i need to build strings using Group_concat and sum prices by vatpercentage where VatPrice is not 0 and price is not 0.
The result i want back in this case:
{a}25{b}45 SEK{c}{a}8{b}9.6 SEK{c}
The code i've tried:
select
group_concat('{a}' ||
CAST(VatPercentage as integer) ||
'{b}' || SUM(VatPrice) ||
' SEK' || '{c}','')
FROM Product
group by VatPercentage
having Count(Price) > 0
Fiddle
Thanks on forehand
Do the regular concatenation in a subquery, then use GROUP_CONCAT in an outer query, because you can't use one aggregation function in the arguments to another.
SELECT GROUP_CONCAT(Result, '|') Results
FROM (
SELECT 'VatPercentage:' || CAST(VatPercentage AS INTEGER) || '% VatPrice: '
|| SUM(VatPrice) Result
FROM Product
WHERE VatPercentage != '0'
GROUP BY VatPercentage) x
You also don't need the HAVING clause. That just excludes results where all the Price values are NULL. But your sample result is skipping rows where VatPercentage is zero, so I've put that in the WHERE clause.
DEMO

SQL count all of the column that has a value greater than 10 and sum it up

I want to count all of the column in my table that has value >= 10.
here is my table :
Date ##### || Value1 || Value2 || Value3
23/04/2014 || __ 1,2 || __ 12,3 ||__ 10 ||
23/04/2014 ||__ 11,2 || ____ 3 || __ 10,3 ||
24/04/2014 || __ 10,9 || ____ 3 || __ 1 ||
I want it to display:
Date ##### || Count ||
23/04/2014 || __ 4 ||
24/04/2014 || __ 1 ||
Assume that I have a lot of date, I want it to display only the last 3 rows.
here is my first code :
Dim strCommand As String = "Select Date, count(*) as tcount from tbBooth having count(*) >= 10 group by date"
already changed based on the solution from Collapsar into this:
Dim strCommand As String = "Select t.d, sum(t.valcount) cnt from (select [date] AS d, CASE WHEN t1.ManualAssists1 >= 10 THEN 1 ELSE 0 END + CASE WHEN t1.ManualAssists2 >= 10 THEN 1 ELSE 0 END + CASE WHEN t1.ManualAssists3 >= 10 THEN 1 ELSE 0 END AS valcount from tbBooth t1) t group by t.d"
it's works, but I want to display only the last 3 row based on ASC order.
Is there anyway how to do it?
Thanks in advances....
try
select t.d
, sum(t.valcount) cnt
from (
select [date] AS d
, CASE WHEN t1.value1 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN t1.value2 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN t1.value3 >= 10 THEN 1 ELSE 0 END
AS valcount
from table t1
) t
group by t.d
;
SELECT
D,
SUM(one + two + three) AS tcount
FROM
(
SELECT
[Date] AS D,
CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END AS one,
CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END AS two,
CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END AS three
FROM
tbBooth
)
GROUP BY
D

Resources