SQL CONCAT multiples fields and multiple rows - sql

I have a little problem with my SQL to concat 2 query in a same row.
Here's my first request:
SELECT lien, id,
CASE WHEN inactif = 0 THEN 'Oui' ELSE 'Non' END AS 'Actif'
FROM redirection.elementsOutils
WHERE lien LIKE '%saaprod/soutien_tache/redirection.asp%'
ORDER BY inactif, dateMAJ
Here's the result:
lien id Actif
http://saaprod/soutien_tache/redirection.asp?id=4466 4467 Oui
Here's my second request (I need id from the precedent result):
SELECT id, clics AS 'Total clics', clicsAnneeActuelle,
nbEmployesAnneActuelle, dateMAJ,
CASE WHEN inactif = 0 THEN 'Oui'ELSE 'Non' END AS 'Actif'
FROM redirection.elementsParAnnee('2021-01-01 00:00:00.0')
WHERE id >0 AND (nom LIKE '%4466%'
OR id LIKE '%4466%' OR lien LIKE '%4466%')
Here's the result:
id Total clics clicsAnneeActuelle nbEmployesAnneActuelle dateMAJ Actif
4466 284 30 18 2021-09-02 Oui
4467 225 28 16 NULL Oui
Here's what I want:
lien id Actif Infos
http://saaprod/soutien_tache/redirection.asp?id=4466 4467 Oui {id:4466, clcis:284 clicsAnneeActuelle:30, nbEmpolyesAnneeActuelle:18, dateMAJ:2021-09-02, Actif:Oui}; {id:4467, clcis:225, clicsAnneeActuelle:28, nbEmpolyesAnneeActuelle:16, dateMAJ:NULL, Actif:Oui}
How I can do that?

You should aggregate the data in the second query and only then do the full join:
select * from (
SELECT lien, id,
CASE WHEN inactif = 0 THEN 'Oui' ELSE 'Non' END AS 'Actif'
FROM redirection.elementsOutils
WHERE lien LIKE '%saaprod/soutien_tache/redirection.asp%'
ORDER BY inactif, dateMAJ
)as a ,
(
SELECT '{'||STRING_AGG('id:'||id||', clics:'||clics||',clicsAnneeActuelle:'||clicsAnneeActuelle||', nbEmployesAnneActuelle:'||nbEmployesAnneActuelle||', dateMAJ:'||dateMAJ||'Actif:'||
CASE WHEN inactif = 0 THEN 'Oui'ELSE 'Non' END,'}; {')||'}' as Infos
FROM redirection.elementsParAnnee('2021-01-01 00:00:00.0')
WHERE id >0 AND (nom LIKE '%4466%' OR id LIKE '%4466%' OR lien LIKE '%4466%')
) as b

Related

I want records with clearence rate > 75. I can't use this in where clause, how should I do it?

Select
suburb,round(100*count(case when result like 'Sold%' Then 1 else null end)/count(*))
AS clearence_rate
from sales
group by suburb
order by suburb;
If you want to filter the result of an aggregate expression you would do
Select suburb, <aggregate expression> AS clearence_rate
from sales
group by suburb
having <aggregate expression> > 75
order by suburb;
There 2 opotion available.
First using CTE:
;WITH CTE AS (
Select
suburb,round(100*count(case when result like 'Sold%' Then 1 else null end)/count(*)) as [value]
AS clearence_rate
from sales
group by suburb
order by suburb
)
Select * from CTE Where [value] > 75
Second option using HAVING cluase:
Select
suburb,round(100*count(case when result like 'Sold%' Then 1 else null end)/count(*)) as [value]
AS clearence_rate
from sales
group by suburb
HAVING round(100*count(case when result like 'Sold%' Then 1 else null end)/count(*)) > 75

BigQuery: [CTE Table name] missing dataset while no default dataset is set in the request

My original table has:
(1) acceptance_rate - string, percentage
(2) host_is_superhost - boolean
I wanted to convert (1) acceptance_rate to integer without the %, so I created a CTE as follow:
WITH acceptance_rate_cte AS
(SELECT
CAST(REPLACE(acceptance_rate,'%',"") AS int) AS new_acceptance_rate,
host_is_superhost AS new_superhost
FROM table1
WHERE acceptance_rate NOT IN ("N/A","0%")
ORDER BY new_acceptance_rate DESC)
SELECT new_acceptance_rate, new_superhost
FROM acceptance_rate_cte;
New CTE table looks like:
new_acceptance_rate | new_superhost
100 | true
90 | true
95 | false
...
NEXT, I wanted to create a table to group all the new_acceptance_rate into buckets of 20 and then count how many true or false are within those buckets. So I did this:
SELECT CASE WHEN new_acceptance_rate >0 AND new_acceptance_rate <= 20 then '1-20'
WHEN new_acceptance_rate >20 AND new_acceptance_rate <=40 then '21-40'
WHEN new_acceptance_rate >40 AND new_acceptance_rate<=60 THEN '41-60'
WHEN new_acceptance_rate >60 AND new_acceptance_rate <=80 THEN '61-80'
ELSE 'Above 80'
END acceptance_range,
new_superhost,
count(*) as superhost_count
FROM acceptance_rate_cte
My expectation for the result is to look like this:
acceptance_range | new_superhost | superhost_count
1-20 | true | 15
1-20 | false | 25
...
But instead i received an error msg as follow:
Error running query Table name "acceptance_rate_cte" missing dataset
while no default dataset is set in the request.
I ran your query above with some sample data it seems to be mostly correct.
with acceptance_rate_cte AS
( SELECT
CAST(REPLACE(acceptance_rate,'%',"") AS int) AS new_acceptance_rate,
host_is_superhost AS new_superhost
FROM table1
WHERE acceptance_rate NOT IN ("N/A","0%")
ORDER BY new_acceptance_rate DESC
)
SELECT CASE WHEN new_acceptance_rate >0 AND new_acceptance_rate <= 20 then '1-20'
WHEN new_acceptance_rate >20 AND new_acceptance_rate <=40 then '21-40'
WHEN new_acceptance_rate >40 AND new_acceptance_rate<=60 THEN '41-60'
WHEN new_acceptance_rate >60 AND new_acceptance_rate <=80 THEN '61-80'
ELSE 'Above 80'
END acceptance_range,
new_superhost,
count(*) as superhost_count
FROM acceptance_rate_cte
GROUP BY acceptance_range, new_superhost;
I did have to add a group by in order for it to execute properly. Based on your error though my guess is you have not run both the CTE and query together in the same session. When you execute run both at the same time.

SQLite - Count and group duplicates

I have a problem figuring out how to count duplicates in a table like below:
Campaign
Approved
Disqualified
campaign-1
1
null
campaign-1
null
2
campaign-2
5
null
campaign-2
null
3
My query:
select
"Campaign"
,case when "Status" = 'Approved' then count("Id") end as "Approved"
,case when "Status" = 'Disqualified' then count("Id") end as "Disqualified"
from "table"
group by "Campaign","Status"
having count(*) > 1
order by "Campaign"
I would like to have a table as result below?
result:
Campaign
Approved
Disqualified
campaign-1
1
2
campaign-2
5
3
...
You must group by Campaign only.
Also, it is easier to use SUM() instead of COUNT(), because SQLite evaluates boolean expressions like Status = 'Approved' as 1 or 0:
SELECT Campaign,
SUM(Status = 'Approved') AS Approved,
SUM(Status = 'Disqualified') AS Disqualified
FROM "table"
GROUP BY Campaign
HAVING COUNT(*) > 1
get_info = """
WITH query1 AS
(
SELECT Campaign,
SUM(Approved) AS sum_a,
SUM(Disqualified) AS sum_d
FROM Campaign
GROUP BY Campaign
)
SELECT Campaign, sum_a, sum_d FROM query1
GROUP BY Campaign
"""

SQL query to (group by ) by condition of column

if I want to make a query that gets the count of users grouping ages
to get the counts each year as alone :
select count(*)
from tbl_user
group by age
how can I make a custom group by so I can get ages in ranges for example ...
like this example :
group by ages as 0-18 , 19-25 , 26-...
Use a CASE expression in a subquery and group by that expression in the outer query:
select age_group, count(*)
from (
select case when age between 0 and 18 then '0-18'
when age between 19 and 26 then '19-25'
...
end as age_group
from tbl_user
) t
group by age_group
SUM 1 and CASE WHEN work in MS SQL Server, which version of SQL are you using?
SELECT
SUM(CASE WHEN Age >= 0 AND Age <= 18 THEN 1 ELSE 0 END) AS [0-18],
SUM(CASE WHEN Age >= 19 AND Age <= 25 THEN 1 ELSE 0 END) AS [19-25]
FROM
YourTable
You could use a CASE statement:
SELECT Sum(CASE WHEN age BETWEEN 0 AND 18 THEN 1 ELSE 0 END) as [0-18],
Sum(CASE WHEN age BETWEEN 19 AND 25 THEN 1 ELSE 0 END) as [19-25],
Sum(CASE WHEN age BETWEEN 26 AND 34 THEN 1 ELSE 0 END) as [26-34]
FROM tbl_user
this will "flatten" the data into one row - to get one row per grouping use this as the basis for a View, then select from that.
Data belongs in a table, not in the code. The age categories are data, IMHO.
CREATE TABLE one
( val SERIAL NOT NULL PRIMARY KEY
, age INTEGER NOT NULL
);
INSERT INTO one (age) SELECT generate_series(0,31, 1);
CREATE TABLE age_category
( low INTEGER NOT NULL PRIMARY KEY
, high INTEGER NOT NULL
, description varchar
);
INSERT INTO age_category (low,high,description) VALUES
( 0,19, '0-18')
, ( 19,26, '19-25')
, ( 26,1111, '26-...')
;
SELECT ac.description, COUNT(*)
FROM one o
JOIN age_category ac ON o.age >= ac.low AND o.age < ac.high
GROUP BY ac.description
;

sql query group

SQL query question
I have a query like
select proposal_id, service_id,account_type
from table1
The result is like this:
proposal_id service_id account_type
1 1001 INTERVAL
1 1002 INTERVAL
2 1003 NON INTERVAL
2 1004 NON INTERVAL
3 1005 NON INTERVAL
3 1006 INTERVAL
I want to write a query: for each proposal_id, if all the service have INTERVAL then get 'INTERVAL', if all NON-INTERVAL get 'NON-INTERVAL', if both, get 'Both'
For the example above, it should return
proposal_id account_type
1 INTERVAL
2 NON-INTERVAL
3 BOTH
Data:
declare #table table (id int, sid int, acc nvarchar(20))
insert #table VALUES (1,1001,'INTERVAL'),(1,1002,'INTERVAL'),(2,1003,'NON INTERVAL'),(2,1004,'NON INTERVAL'),
(3,1005,'NON INTERVAL'),(3,1006,'INTERVAL')
Query:
select x.Id
, CASE counter
WHEN 1 THEN x.Account_Type
ELSE 'BOTH'
END AS Account_Type
from (
select Id, Count(DISTINCT(acc)) AS counter, MAX(acc) As Account_Type
from #table
GROUP BY Id
) x
Results
Id Account_Type
----------- --------------------
1 INTERVAL
2 NON INTERVAL
3 BOTH
SELECT
b.proposal_id
,CASE
WHEN s1.proposal_id IS NOT NULL AND s2.proposal_id IS NOT NULL THEN 'BOTH'
WHEN s1.proposal_id IS NOT NULL THEN 'INTERVAL'
WHEN s2.proposal_id IS NOT NULL THEN 'NON-INTERVAL'
ELSE 'UNKNOWN'
END [account_type]
FROM table1 b
LEFT JOIN(
SELECT proposal_id,account_type FROM table1 WHERE account_type = 'INTERVAL'
) s1
ON b.proposal_id = s1.proposal_id
LEFT JOIN (
SELECT proposal_id,account_type FROM table1 WHERE account_type = 'NON-INTERVAL'
)s2
ON b.proposal_id = s2.proposal_id
You could use count distinct to determinate if it is both then use CASE to determinate what to display
SELECT DISTINCT proposal.proposal_id,
CASE cou
WHEN 1 THEN type ELSE 'Both' END as TYPE
FROM proposal
INNER JOIN (SELECT proposal_id, count(distinct type) cou
FROM proposal GROUP BY proposal_id) inn
ON proposal.id = inn.id
select proposal_id,
case when count(distinct account_type) > 1 then 'BOTH'
else max(account_type)
end
from table1
group by proposal_id
You have the fiddler here.