i have a column that has month number stored as integer. i would like to create a new column with the quater of each month. is there an simpler way of doing the same, i have to use this in multiple places. so just wanted to check if there is any simpler way of doing this.
currently i am using below to achieve it
case when tt1.resolved_month in (1,2,3) then 1
when tt1.resolved_month in (4,5,6) then 2
when tt1.resolved_month in (7,8,9) then 3
when tt1.resolved_month in (10,11,12) then 4
end as quater
i checked the Quarter function and it doesnt support number as input.
CEIL function will get the quarter.
SELECT CEIL(resolved_month / 3) AS quarter
Demonstration:
Month Month/3 Quarter
-------------------------
1 0.3333 1
2 0.6667 1
3 1 1
4 1.3333 2
5 1.6667 2
6 2 2
7 2.3333 3
8 2.6667 3
9 3 3
10 3.3333 4
11 3.6667 4
12 4 4
Working Fiddle
Instead of a case expression, you could divide the month by 3 and ceil the result:
SELECT CEIL(resolved_month / 3) AS quarter
FROM tt1
As #exudong suggested in the comments, it may be a good idea to encapsulate this logic in a function and re-use it wherever needed.
You could use the QUARTER() function:
SELECT
resolved_month,
QUARTER(ADDDATE('2021-01-01',INTERVAL resolved_month-1 MONTH)) as quarter2
FROM months;
Fiddle
The advantage (😉) is that everybody who read this will recognize that the quarter is being calculated.
Related
Here is a problem. I need to find working days between two dates (without weekends). I currently found and was able to successfully use this approach:
SELECT 5 * (DATEDIFF(DateClosed, DateOpened) DIV 7) + MID('0123455501234445012333450122234501101234000123450',
7 * WEEKDAY(DateOpened) + WEEKDAY(DateClosed) + 1, 1) AS TotalResolutionTimeBusinessDays
FROM table1
This is a complex calculation based on a matrix:
| M T W T F S S
-|--------------
M| 0 1 2 3 4 5 5
T| 5 0 1 2 3 4 4
W| 4 5 0 1 2 3 3
T| 3 4 5 0 1 2 2
F| 2 3 4 5 0 1 1
S| 0 1 2 3 4 0 0
S| 0 1 2 3 4 5 0
In the matrix, the intersection of any given x and y value pair (WEEKDAY(#S) and WEEKDAY(#E) yields the difference in work days between the two values. The 49 values in the table are concatenated into the following string: 0123455501234445012333450122234501101234000123450.
This works fine for me but now I need to present difference between dates in another format. E.g.: Let's say we have two dates: StartDate = '2013-06-28 01:27:35' and EndDate = '2013-07-08 16:47:21'. If we use method described above we get 7 working days which is correct. But I need to count all the difference between dates(including hours and minutes) so it could look like
SELECT TIME_TO_SEC(TIMEDIFF('2013-07-08 16:47:21','2013-06-28 01:27:35')) / 3600 / 24
which without weekends should be value like 7.64 days.
Any suggestions how to write a calculation based on that format? Any help would be much appreciated.
I have a column in table A. the column name is Sequence number. The Structure of table A is numbers from 1,2,3,4.....3600.
Now on the basis of table A. I want the below output from the SQL select query for SQL server 2008.
seq no dynamic col
1 1
2 1
3 1
4 1
5 1
6 2
7 2
8 2
9 2
10 2
11 2
12 3
13 3
My Second column is getting generated at the run time.
And the business logic is that, if the seq number mod 6 = 0 then increment the value of dynamic column.
Thanks in advance
Try this:
select seqno, (seqno/6) +1 dynamiccol
from t
Fiddle Demo
Take this as pseudo code because I'm not familiar with SQL Server specifically, but it should give you somewhere to go.
SELECT
seq_no,
ROUNDDOWN(seq_no/6)+1 AS dynamic_col
FROM
my_table
I have created the following tables with ranks for a data set:
Position Index IndexL IndexH Amount Rank
1 2.5 2 3 2000 1
1 2.5 2 3 3000 2
1 2.5 2 3 4000 3
1 2.5 2 3 5000 4
1 2.5 2 3 6000 5
2 1.5 1 2 2500 1
2 1.5 1 2 4500 2
2 1.5 1 2 6700 3
2 1.5 1 2 8900 4
2 1.5 1 2 9900 5
Now I want to find the percentile based on the ranks created using the indices such that I get the following output :
Position Amount
1 3000+(4000-3000)*(2.5-2)
2 2500+(4500-2500)*(1.5-1)
Can someone help me with this. I am kinda new to SQL world.
Thanks,
Monica
I think you can do what you want with the percentile_cont() aggregation function. It looks like you want the median:
SELECT position,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY Amount) as Median
from t
group by position;
You can read more about it here.
You can have Oracle assign a percentile for you using the NTILE analytic function:
SELECT
position,
amount,
NTILE(100) OVER (PARTITION BY POSITION ORDER BY amount)
FROM myTable
I'm not sure if the result will match your calculations (I'm a bit hazy on some of my statistics). If not, please try the PERCENTILE_CONT solution proposed by #GordonLinoff, or else you can try the PERCENT_RANK analytic function - just replace NTILE(100) in the query above with PERCENT_RANK().
I have one employee table which contains:
emp id Sum
------ ---
1 7
2 6
I want a SQL query for getting the quotient and remainder when dividing the Sum with 8.
Use integer division and mod operators to get the quotient and remainder:
SELECT
emp_id,
sum,
sum / 8 AS Result,
sum div 8 AS Quotient,
sum mod 8 AS Remainder
FROM employee
emp_id sum Result Quotient Remainder
1 7 0.8750 0 7
2 6 0.7500 0 6
3 9 1.1250 1 1
4 10 1.2500 1 2
5 11 1.3750 1 3
6 12 1.5000 1 4
7 13 1.6250 1 5
8 14 1.7500 1 6
9 15 1.8750 1 7
10 16 2.0000 2 0
What will be the return type of your qoutient? If you don't care if its a floating point or an integer(whole number). You can try this.
SELECT
(sum / 8) AS qoutient,
(sum % 8) AS reminder
FROM employee
You can use the mysql function DIV to get the qoutient
(http://dev.mysql.com/doc/refman/5.0/en/arithmetic-functions.html#operator_div) :
SELECT 14 DIV 3
will return 4
It should do the trick
As for the remainder, others have replied
you can use the % operator to get the remainder. Here's an example.
SELECT Round(17 / 4) -- quotient without decimal
SELECT 17 % 4 -- remainder
For my PL/SQL function I usually use:
SELECT trunc(sum/8) --- Quotient
SELECT mod(sum/8) -- Remainder
use floor function, select floor(column_name/divisor) from dual
I'm way out of my league here...
I have a mapping table (table1) to assign particular values (value) to a whole number (map_nu). My second table (table2), is a collection of averages (avg) for each user (user_id).
(I couldn't figure out how to properly make a markdown table, please feel free to edit!)
table1: table2:
(value)(Map_nu) (user_id)(avg)
---- -----
1 1 1 1.111
1.045 2 2 1.2
1.09 3 3 1.33333
1.135 4 4 1
1.18 5 5 1.389
1.225 6 6 1.42
1.27 7 7 1.07
1.315 8
1.36 9
1.405 10
The value Map_nu is a special number that each user gets assigned according to their average. I need to find a way to match the averages from table2 to the closest value in table1. I only need to match to the 2 digit past the decimal, so I've added the Truncated function
SELECT table2.user_id, map_nu
FROM `table1`
JOIN table2 ON TRUNCATE(table1.value,2)=TRUNCATE(table2.avg,2)
I still miss the values that don't match the averages exactly. Is there a way to pick the nearest truncated value or even to round to the second decimal? Rounding up/down wont matter as long as its applied to all values the same.
I am trying to have the following result (if rounded up):
(user_id)(Map_nu)
----
1 4
2 6
3 6
4 1
5 10
6 11
7 3
Thanks!
i think you might have to do this in 2 separate queries. there is no 'nearest' operator in sql, so you can either calculate it in your software, or you could use
select map_nu from table1 ORDER BY abs(value - $avg) LIMIT 1
inside a loop. however, that cannot be used as a join function as it requires the ORDER and LIMIT which are not valid as joins.
another way of looking at it is it seems that your map_nu and value are deterministic in relation to each other - value = 1 + ((map_nu - 1) * 0.045) - so maybe you could make use of that fact and calculate an integer based on that equation? assuming that relationship holds true for all values of map_nu.
This is an awkward database design. What is the data representing and what are you trying to solve? There might be a better way.
Maybe do something like...
SELECT a.user_id, b.map_nu, abs(a.avg - b.value)
FROM
table2 a
join table1 b
left join table1 c on abs(a.avg - b.value) > abs(a.avg - c.value)
where c.value is null
order by a.user_id
Doesn't actually produce the same output as the one you were expecting for (doesn't do any rounding). Though you should be able to tweak it from there. Above query will produce the output below (w/ data you've provided):
user_id map_nu abs(a.avg - b.value)
------- ------ --------------------
1 3 0.0209999999999999
2 5 0.02
3 8 0.01833
4 1 0
5 10 0.016
6 10 0.0149999999999999
7 3 0.02
Beware though if you're dealing with large tables. Evaluate the explain of the above query if it'll be practical to run it within MySQL or if better to be done outside it.
Note 2: Will produce duplicate rows if there are avg values that are equi-distant to value values within table1 (Ex. if value for map_nu's 11 and 12 are 2 and 3 and someone get's an avg of 2.5). Your question doesn't really specify what to do for that so you might want to take that into account.
Its taking a little extra work, but I figure the easiest way to get my results will be to map all values to the second decimal place in table1:
1 1
1.01 1
1.02 1
1.03 1
1.04 1
1.05 2
1.06 2
1.07 2
1.08 2
1.09 3
1.1 3
1.11 3
1.12 3
1.13 3
1.14 4
...
Thanks for the suggestions! Sorry I couldn't present the question more clear.