Categorizing Data with SQL Statement to Import Data - sql-server-2008-r2

This is for SQL Server 2008 R2.
I have a table PEOPLE with a columns NAME and AGE. I am importing with a SQL Job to another table LEADS with the same columns NAME and AGE, and with an additional column, AGEGROUP where I want that
Ages < 20 go into Group A
Ages 21-39 go into Group B
Ages 40-59 go into Group C
Ages >= 60 go into Group D
How would that SQL Statement be?
Thanks.

This insert would do what you want (your logic would have missed anyone that was 20, so I put them in Group A)
INSERT INTO LEADS (NAME, AGE, AGEGROUP)
SELECT
NAME
, AGE
, CASE
WHEN AGE <= 20 THEN 'A'
WHEN AGE > 20 AND AGE < 40 THEN 'B'
WHEN AGE >= 40 AND AGE < 60 THEN 'C'
WHEN AGE >= 60 THEN 'D'
END AS AGEGROUP
FROM PEOPLE

INSERT INTO LEADS (Name , Age , AgeGroup)
SELECT Name
,Age
,CASE WHEN Age <= 20 THEN 'A'
WHEN Age > 20 AND Ages < 40 THEN 'B'
WHEN Age >= 40 AND Ages < 60 THEN 'C'
WHEN Age >=60 THEN 'D'
END
FROM People

Related

How to create buckets and groups within those buckets using PostgresQL

How to find the distribution of credit cards by year, and completed transaction. Group these credit cards into three buckets: less than 10 transactions, between 10 and 30 transactions, more than 30 transactions?
The first method I tried to use was using the width_buckets function in PostgresQL, but the documentation says that only creates equidistant buckets, which is not what I want in this case. Because of that, I turned to case statements. However, I'm not sure how to use the case statement with a group by.
This is the data I am working with:
table 1 - credit_cards table
credit_card_id
year_opened
table 2 - transactions table
transaction_id
credit_card_id - matches credit_cards.credit_card_id
transaction_status ("complete" or "incomplete")
This is what I have gotten so far:
SELECT
CASE WHEN transaction_count < 10 THEN “Less than 10”
WHEN transaction_count >= 10 and transaction_count < 30 THEN “10 <= transaction count < 30”
ELSE transaction_count>=30 THEN “Greater than or equal to 30”
END as buckets
count(*) as ct.transaction_count
FROM credit_cards c
INNER JOIN transactions t
ON c.credit_card_id = t.credit_card_id
WHERE t.status = “completed”
GROUP BY v.year_opened
GROUP BY buckets
ORDER BY buckets
Expected output
credit card count | year opened | transaction count bucket
23421 | 2002 | Less than 10
etc
You can specify the bin sizes in width_bucket by specifying a sorted array of the lower bound of each bin.
In you case, it would be array[10,30]: anything less than 10 gets bin 0, between 10 and 29 gets bin 1 and 30 or more gets bin 2.
WITH a AS (select generate_series(5,35) cnt)
SELECT cnt, width_bucket(cnt, array[10,30])
FROM a;
To figure this out you need to count transactions per credit card in order to figure out the right bucket, then you need to count the credit cards per bucket per year. There are a couple of different ways to get the final result. One way is to first join up all your data and compute the first level of aggregate values. Then compute the final level of aggregate values:
with t1 as (
select year_opened
, c.credit_card_id
, case when count(*) < 10 then 'Less than 10'
when count(*) < 30 then 'Between [10 and 30)'
else 'Greater than or equal to 30'
end buckets
from credit_cards c
join transactions t
on t.credit_card_id = c.credit_card_id
where t.transaction_status = 'complete'
group by year_opened
, c.credit_card_id
)
select count(*) credit_card_count
, year_opened
, buckets
from t1
group by year_opened
, buckets;
However, it may be more perforamant first calculate the first level of aggregate data on the transactions table before joining it to the credit cards table:
select count(*) credit_card_count
, year_opened
, buckets
from credit_cards c
join (select credit_card_id
, case when count(*) < 10 then 'Less than 10'
when count(*) < 30 then 'Between [10 and 30)'
else 'Greater than or equal to 30'
end buckets
from transactions
group by credit_card_id) t
on t.credit_card_id = c.credit_card_id
group by year_opened
, buckets;
If you prefer to unroll the above query and uses Common Table Expressions, you can do that too (I find this easier to read/follow along):
with bkt as (
select credit_card_id
, case when count(*) < 10 then 'Less than 10'
when count(*) < 30 then 'Between [10 and 30)'
else 'Greater than or equal to 30'
end buckets
from transactions
group by credit_card_id
)
select count(*) credit_card_count
, year_opened
, buckets
from credit_cards c
join bkt t
on t.credit_card_id = c.credit_card_id
group by year_opened
, buckets;
Not sure if this is what you are looking for.
WITH cte
AS (
SELECT c.year_opened
,c.credit_card_id
,count(*) AS transaction_count
FROM credit_cards c
INNER JOIN transactions t ON c.credit_card_id = t.credit_card_id
WHERE t.STATUS = 'completed'
GROUP BY c.year_opened
,c.credit_card_id
)
SELECT cte.year_opened AS 'year opened'
,SUM(CASE
WHEN transaction_count < 10
THEN 1
ELSE 0
END) AS 'Less than 10'
,SUM(CASE
WHEN transaction_count >= 10
AND transaction_count < 30
THEN 1
ELSE 0
END) AS '10 <= transaction count < 30'
,SUM(CASE
WHEN transaction_count >= 30
THEN 1
ELSE 0
END) AS 'Greater than or equal to 30'
FROM CTE
GROUP BY cte.year_opened
and the output would be as below.
year opened | Less than 10 | 10 <= transaction count < 30 | Greater than or equal to 30
2002 | 23421 | |

how to get list from 1 to 10 and from 11 to 20 values (postgres)

SELECT * FROM users WHERE user_name = 'Andrew' ORDER BY age DESC
Here I have some call . For example I have db in which I have 3 columns :
user_name, age , id
In this db we have 30 the same names ('Andrew') . I want to make order by age as u see above and get list from 1 to 10 , then from 11 to 20 ,then from 21 to 30 .How to make it ?
/get-users/:from/:to
You may use LIMIT and OFFSET, e.g. to get records 11-20 you could do this:
SELECT *
FROM users
WHERE user_name = 'Andrew'
ORDER BY age DESC
OFFSET 10 LIMIT 10;

PostgreSQL How to check range of integer in case statement

I am having problem to fetch query in which i have a check user score in range to display the grade if user score between 75 and 100 then its A. If user score between 60- 75 then its B and .. so on .
I am getting this values
CASE users.points_earned
WHEN 75-100 THEN
'A+'
WHEN 60-75 THEN
'A'
WHEN 40-60 THEN
'B+'
WHEN 1--40 THEN
'B'
ELSE
'Absent'
end as rank
buts not working how to check range in case statement of postgresql
You can use BETWEEN for check ranges.
WITH users(points_earned) as(
select 75
union all
select 90
union all
select 200
)
SELECT CASE
WHEN users.points_earned BETWEEN 40 AND 75 THEN 'A+'
WHEN users.points_earned BETWEEN 76 AND 100 THEN 'A'
ELSE 'Absent'
END as rank
FROM users

Not getting desired format from Oracle query

I am trying to fetch data from data base in below format,
Month Count
----- -----
201208 124
201209 0
201210 56
201211 25
201212 0
201301 184
201302 0
In database I have entries like,
Month Count
----- -----
201206 56
201208 124
201210 56
201211 25
201301 184
201304 49
Below is my query,
SELECT MONTH, Count
FROM TABLE_NAME
WHERE MONTH BETWEEN 201208 AND 201302
AND ID = 'X'
Output :
Month Count
----- -----
201208 124
201210 56
201211 25
201301 184
Can anyone help me getting data in desired format.
First you should generate full month's sequence between these dates. You can do it with CONNECT BY LEVEL in Oracle. then just JOIN this sequence with your table:
SELECT MonthSeq.MONTH,
NVL(Count,0) Count
FROM TABLE_NAME
RIGHT JOIN
(
SELECT
TO_CHAR(ADD_MONTHS(TO_DATE('201208','YYYYMM'),
(ROWNUM-1))
,'YYYYMM') MONTH
FROM DUAL
CONNECT BY LEVEL<=
MONTHS_BETWEEN(TO_DATE('201302','YYYYMM') ,
TO_DATE('201208','YYYYMM'))+1
) MonthSeq
ON TABLE_NAME.MONTH=MonthSeq.MONTH
ORDER BY MonthSeq.MONTH
SQLFiddle demo
UPD:
Your query from the comment should looks like the following. You should move WHERE condition to the JOIN ON. If you use it in WHERE you don't get rows with zero counts.
SELECT MonthSeq.MONTH,
NVL(SUM(TOTAL_SESSIONS),0) AS SESSIONS
FROM X
RIGHT JOIN
(
SELECT
TO_CHAR(ADD_MONTHS(TO_DATE('201208','YYYYMM'),
(ROWNUM-1))
,'YYYYMM') MONTH
FROM DUAL
CONNECT BY LEVEL<=
MONTHS_BETWEEN(TO_DATE('201302','YYYYMM') ,
TO_DATE('201208','YYYYMM'))+1
) MonthSeq
ON X.MONTH=MonthSeq.MONTH and X.acct_id = 'ABCD'
ORDER BY MonthSeq.MONTH
You need to use TO_DATE function to convert the month field to DATE format. Refer here for more in detail. Try like this,
SELECT TO_CHAR(TO_DATE(MONTH, 'YYYYMM'), 'YYYYMM') month, count
FROM TABLE_NAME
WHERE month BETWEEN TO_DATE('201208', 'YYYYMM') AND TO_DATE('201302', 'YYYYMM')
AND id = 'X'
ORDER BY TO_DATE(month, 'YYYYMM');

TSQL Join to get all records from table A for each record in table B?

I have two tables:
PeriodId Period (Periods Table)
-------- -------
1 Week 1
2 Week 2
3 Week 3
EmpId PeriodId ApprovedDate (Worked Table)
----- -------- ------------
1 1 Null
1 2 2/28/2013
2 2 2/28/2013
I am trying to write a query that results in this:
EmpId Period Worked ApprovedDate
----- -------- --------- ------------
1 Week 1 Yes Null
1 Week 2 Yes 2/28/2013
1 Week 3 No Null
2 Week 1 No Null
2 Week 2 Yes 2/28/2013
2 Week 3 No Null
The idea is that I need each Period from the Periods table for each Emp. If there was no record in the Worked table then the 'No' value is placed Worked field.
What does the TSQL look like to get this result?
(Note: if it helps I also have access to an Employee table that has EmpId and LastName for each employee. For performance reasons I'm hoping not to need this but if I do then so be it.)
You should be able to use the following:
select p.empid,
p.period,
case
when w.PeriodId is not null
then 'Yes'
else 'No' End Worked,
w.ApprovedDate
from
(
select p.periodid, p.period, e.empid
from periods p
cross join (select distinct EmpId from worked) e
) p
left join worked w
on p.periodid = w.periodid
and p.empid = w.empid
order by p.empid
See SQL Fiddle with Demo