Order an SQL table by year and ranges of years - sql

I would like to be able to order the results in the following way.
There are two columns, one stores years and the other year ranges, and, sometimes, dates, like this:
2017
2016
2014–2016
1980-ongoing
2013
2000 28-27 March
1970
At the moment, I concatenate them and order by DESC, Getting this (showing the concatenated temporary column):
order by CONCAT(IFNULL(CAST(Year_Pub AS VARCHAR(16)) THEN '' ELSE CAST(Year_Pub AS VARCHAR(16))), IFNULL(Date_Freeform THEN '' ELSE Date_Freeform)) DESC
The result is:
2017
2016
2014-2016
2013
200028-27 March
1980-ongoing
1970
However, what I would like to get is this (imagine that this is a list of activities for a CV or similar):
1980-ongoing
2017
2016
2014-2016
2013
2000
1970
That is if there is a span of years, I would like to have the ongoing engagements to appear first, ordered by the start year, then have spans of years ordered by last year and mixed with single years. Dates only occur when Year_Pub is NULL and will have to be removed before concatenation, I imagine.
The separator is an ndash, so I need to split those strings by that somehow as I see from examples that show how to order by the family names in tables that have first name and family name in one column but this is a more complicated situation and I am not really familiar with SQL.
Also, this operation will be performed on a table that comes with an application so I do not want to insert data or columns into their database in case something gets broken.
Using SQL on an ElevateDB database (SQL 2003 standard (ANSI ISO/IEC 9075:2003), but a generic solution will do, I can look up the syntax).
Thank you for the advice.

This is one way to achieve your result:
SELECT
year_pub,
date_freeform,
COALESCE(CAST(year_pub AS VARCHAR(4)), date_freeform) AS year_list
FROM
table_name
ORDER BY
COALESCE(CAST(year_pub AS VARCHAR(4)),
CASE WHEN RIGHT(date_freeform, 4) = 'oing'
THEN '9999'
ELSE RIGHT(date_freeform, 4)
END
) DESC,
date_freeform DESC;

Related

Get multiple columns for different WHERE clause on the same column in SQL

I have a table and column containing date (say in string). I need to get two columns such as countin(2020) and countin(2019) from the same date column such that date is like '2020%' or '2019%' and I want them as separate columns.
My query is kind of like this.
select C.pin_code, count(distinct(C.customer_code)) as 2020
from table
group by C.pin_code
My output is this
For me there should be another column beside 2020 called 2019 which give same data as 2020 in year 2019.
If I have under emphasized something, please let me know in the comments.
Select
Count(Year(year_col)) as year,
Pin_code
From T
Group_by pin_code
Order by pin_code desc;
You can use pivot in case you need those values in year column
For me there should be another column beside 2020 called 2019 which give same data as 2020 in year 2019.
If your data has a date in it, then I would expect a query like this:
select C.pin_code,
count(distinct case when year(C.date) = 2020 then C.customer_code end) as cnt_2020,
count(distinct case when year(C.date) = 2019 then C.customer_code end) as cnt_2019
from C
group by C.pin_code;
Date/time functions are notoriously database dependent. But year() is pretty common and all databases have this functionality somehow.

Selecting only year from a given Date

I have created a employee table with column as Date_Of_Joining.
I have entered the data in YYYY-MM-DD Format.
Now I want to retrieve the data of the employee only by using the YEAR.
For example if I have entered Date_Of_Joining as 2010-10-15, 2012-05-18 and 2008-04-16.
Now I want the details of the employee whose Date_Of_Joining is after 2010.
try do a query like this
select * from employee-table where year(Date_Of_Joining) > 2010
Replace "employee-table" with your table name.
This query will give all the data that is after year 2010
SELECT * FROM Employee WHERE YEAR(Date_Of_Joining) > 2010
If Date_Of_Joining datatype is DATE the query will work, if the data type is varchar, then you need to convert it into DATE format then apply the query.
In case if you want to filter with month and year, you can use as
SELECT * FROM Employee
WHERE YEAR(Date_Of_Joining) > 2010 AND MONTH(Date_Of_Joining) > 1
If the range between Jan 2010 and May 2013, you can use as
SELECT * FROM Employee
WHERE (YEAR(Date_Of_Joining) >= 2010 AND MONTH(Date_Of_Joining) >= 1)
OR (YEAR(Date_Of_Joining) <= 2013 AND MONTH(Date_Of_Joining) <= 5)
just follow this
SELECT YEAR(Date_Of_Joining)
it is the general format to get year
I strongly recommend that you phrase this as:
Date_Of_Joining >= '2011-01-01'
That is, you should avoid using the expression YEAR(Date_Of_Joining). Why? Using a function on a column prevents certain optimization strategies -- especially those using indexes and partitions.
For this particular example, you probably have a small amount of data, so it won't actually affect the performance of this query. But you might as well learn how to write with performance in mind.

SQL store results table with month name

I have several CSV's stored to query against. Each CSV represents a month of data. I would like to count all the records in each CSV and save that data to a table as a row in the table. For instance, the table that represents May should return something that looks like this with June following. The data starts in Feb 2018 and continues to Feb 2019 so year value would be needed as well.
Month Results
----------------
May 18 1170
June 18 1167
I want to run the same query against all the tables for purposes of efficiency. I also want the query to work with all future updates eg. a March 19 table gets added, and the query will still work.
So far, I have this query.
SELECT COUNT(*)
FROM `months_data.*`
I am querying in Google Big Query using Standard SQL.
It sounds like you just want an aggregation that counts rows for each month:
SELECT
DATE_TRUNC(DATE(timestamp), MONTH) AS Month,
COUNT(*) AS Results
FROM `dataset.*`
GROUP BY month
ORDER BY month
You can use the DATE_FORMAT function if you want to control the formatting.
You seem to need union all:
select 2018 as yyyy, 2 as mm, count(*) as num
from feb2018
union all
select 2018 as yyyy, 3 as mm, count(*)
from mar2018
union all
. . .
Note that you have a poor data model. You should be storing all the data in a single table with a date column.

SQL: Can GROUP BY contain an expression as a field?

I want to group a set of dated records by year, when the date is to the day. Something like:
SELECT venue, YEAR(date) AS yr, SUM(guests) AS yr_guests
FROM Events
...
GROUP BY venue, YEAR(date);
The above is giving me results instead of an error, but the results are not grouping by year and venue; they do not appear to be grouping at all.
My brute force solution would be a nested subquery: add the YEAR() AS yr as an extra column in the subquery, then do the grouping on yr in the outer query. I'm just trying to learn to do as much as possible without nesting, because nesting usually seems horribly inefficient.
I would tell you the exact SQL implementation I'm using, but I've had trouble discovering it. (I'm working through the problems on http://www.sql-ex.ru/ and if you can tell what they're using, I'd love to know.) Edited to add: Per test in comments, it is probably not SQL Server.
Edited to add the results I am getting (note the first two should be summed):
venue | yr | yr_guests
1 2012 15
1 2012 35
2 2012 12
1 2008 15
I expect those first two lines to instead be summed as
1 2012 50
Works Fine in SQL Server 2008.
See working Example here: http://sqlfiddle.com/#!3/3b0f9/6
Code pasted Below.
Create The Events Table
CREATE TABLE [Events]
( Venue INT NOT NULL,
[Date] DATETIME NOT NULL,
Guests INT NOT NULL
)
Insert the Rows.
INSERT INTO [Events] VALUES
(1,convert(datetime,'2012'),15),
(1,convert(datetime,'2012'),35),
(2,convert(datetime,'2012'),12),
(1,convert(datetime,'2008'),15);
GO
-- Testing, select newly inserted rows.
--SELECT * FROM [Events]
--GO
Run the GROUP BY Sql.
SELECT Venue, YEAR(date) AS yr, SUM(guests) AS yr_guests
FROM Events
GROUP BY venue, YEAR(date);
See the Output Results.
VENUE YR YR_GUESTS
1 2008 15
1 2012 50
2 2012 12
it depends of your database engine (or SQL)
to be sure (over different DB Systems & Versions), make a subquery
SELECT venue, theyear, SUM(guests) from (
SELECT venue, YEAR(date) AS theyear, guest
FROM Events
)
GROUP BY theyear
you make a subtable of
venue, date as theyear, guest
aaaa, 2001, brother
aaaa, 2001, bbrother
bbbb, 2001, nobody
... and so on
and then
count them

To display only previous three months even the months before is not exist in database

Below is my new sql so far as i do not manage to use Dale M advice,
SELECT
all_months.a_month_id AS month,
year($P{date}) as year,
count(case when clixsteraccount.rem_joindate between DATE_FORMAT($P{date}-INTERVAL 2 MONTH, '%Y-%m-01') AND $P{date} THEN clixsteraccount.rem_registerbycn end) AS
total_activation,
'ACTIVATION(No)' AS fake_column
FROM clixsteraccount right join all_months on all_months.a_month_id = date_format(clixsteraccount.rem_joindate,'%m') and
(clixsteraccount.rem_registrationtype = 'Normal')and(clixsteraccount.rem_kapowstatus='pending' or clixsteraccount.rem_kapowstatus='success')
GROUP BY year,month
HAVING month BETWEEN month(date_sub($P{date},interval 2 month)) and month($P{date})
So, what i do is create a table with two fields, a_month_id(1,2,3...,12) and a_month(name of months). Sql above does give me what i want which is to display previous 3 months even the months before is not exist.
exp: data start on July. So, i want to display May,June and July data like 0,0,100.
The problem occur when it comes to next months or next year. When i try to generate sql based on parameter on Jan, it doesn't work like i thought. I do realize the problem are with 'Having' condition. Do anyone have idea how to improvised this sql to make it continue generate in the next,next year.
Thank you in advanced.
OK, I will make a few suggestions and give you an answer that will work on SQL Server - you will need to make any translations yourself.
I note that your query will aggregate all years together, i.e. Dec 2012 + Dec 2013 + Dec 2014 etc. Based on your question I don't think that is your intention so I will keep each distinct. You can change the query if that was your intention. I have also not included your selection criteria (other than by the month).
I suggest that you utilize an index table. This is a table stored in your database (or the master database if possible) with an clustered indexed integer column running from 0 to n where n is a sufficiently large number - 10,000 will be more than enough for this application (there are 12 months in a year so 10,000 represents 833 years). This table is so useful everyone should have one.
SELECT DATEADD(month, it.id, 0 ) AS month
,ISNULL(COUNT(clixsteraccount.rem_registerbycn), 0) AS registration
,'REGISTRATION(No)' AS fake_column
FROM cn
INNER JOIN ON ca.rem_registerbycn = cn.cn_id
clixsteraccount ca
RIGHT JOIN
IndexTable it ON it.id = DATEDIFF(month, 0, clixsteraccount.rem_joindate)
WHERE it.id BETWEEN DATEDIFF(month, 0, #StartDate) - 3 AND DATEDIFF(month, 0, GETDATE())
GROUP BY it.id
The way it works is by converting the clixsteraccount.rem_joindate to an integer that represents the number of months since date 0 (01-01-1900 in SQL Server). This is then matched to the id column of the IndexTable and limited by the dates you select. Because every number exists in the index table and we are using an outer join it doesn't matter if there are months missing from your data.