Error: SQLite query - no such function: monthname
(1) By anonymous on 2022-04-08 03:07:24 [link] [source]
The following SQLite3 (Windows 11) query on sakila-db..
SELECT monthname(rental_date) rental_month, count( * ) num_rentals FROM rental WHERE rental_date BETWEEN '2005-05-01' AND '2005-08-01' GROUP BY monthname(rental_date);
produces..
Error while executing SQL query on database 'sakila': no such function: monthname
..so monthname function in MySQL but not SQLite3?
(2) By Harald Hanche-Olsen (hanche) on 2022-04-08 04:56:49 in reply to 1 [link] [source]
I don’t know about MySQL, but that is not among SQLite’s Date And Time Functions.
You could make your own twelve row table and use a JOIN to get what you want.
(3.3) By cj (sqlitening) on 2022-04-08 06:34:52 edited from 3.2 in reply to 1 [link] [source]
https://stackoverflow.com/questions/650480/get-month-from-datetime-in-sqlite Converted method used in above link to a PowerBASIC macro. macro monthname(ColumnName)="substr('JanFebMarAprMayJunJulAugSepOctNovDec', 1 + 3*strftime('%m',"+ColumnName+"),-3)month" #INCLUDE "sqlitening.inc" FUNCTION PBMAIN AS LONG slopen ":memory:" slexe "create table t1(c1 text) slexe "insert into t1 values(date('now'))" MSGBOX slselstr("select " + monthname("c1") + " from t1") END FUNCTION MSGBOX slselstr("select substr('JanFebMarAprMayJunJulAugSepOctNovDec', 1 + 3*strftime('%m',c1),-3)as month from t1")
(4) By Ryan Smith (cuz) on 2022-04-08 09:14:53 in reply to 1 [link] [source]
Quite correct, it doesn't.
The problem is that Monthname() (or its possible equivalent placeholder within strftime()) would require localization data, since the names of months may differ for every language/country.
SQLite does not hold any localization formatting data, and doing so inside itself would be a gross violation of the "Lite" moniker.
You are however easily able to add your own functions, or tables, containing all the localization and month-names your heart desires (obviously), but it is not a standard core function of SQLite at this point.
As a workaround, I like cj's macro, in SQLite this slightly bulky function will work:
substr('--JanFebMarAprMayJunJulAugSepOctNovDec', CAST( strftime('%m', {reference_date}) AS INTEGER) * 3, 3)
or, for full month-names:
trim(substr('-------January February March April May June July August SeptemberOctober November December', CAST( strftime('%m', {reference_date}) AS INTEGER) * 9, 9))
Here is a script making a mock-up of your database, two possible views to use and queries that will work using those views:
CREATE TABLE rental(rental_date);
INSERT INTO rental VALUES
('2005-05-01')
,('2005-05-15')
,('2005-05-20')
,('2005-06-01')
,('2005-06-02')
,('2005-07-01')
,('2005-08-01')
,('2005-08-02')
,('2005-08-03')
,('2005-08-15')
;
-- A view based on your table that calculates the month-name for every entry (based on cj's macro)
CREATE VIEW rental_months AS
SELECT rental_date,
substr('--JanFebMarAprMayJunJulAugSepOctNovDec',CAST(strftime('%m',rental_date) AS INTEGER)*3,3) AS rental_month
FROM rental
;
-- Your query using the view
SELECT rental_month, count(*) AS num_rentals
FROM rental_months
WHERE rental_date BETWEEN '2005-05-01' AND '2005-08-01'
GROUP BY rental_month;
-- rental_month|num_rentals
-- ------------|---------
-- Aug | 1
-- Jul | 1
-- Jun | 2
-- May | 3
-- A view of the months, in any language you please (I used a mix):
CREATE VIEW month_names AS
SELECT 0 AS idx, 'Invalid-Month' AS month_name UNION ALL
SELECT 1, 'January' UNION ALL
SELECT 2, 'February' UNION ALL
SELECT 3, 'March' UNION ALL
SELECT 4, 'Avril' UNION ALL
SELECT 5, 'May' UNION ALL
SELECT 6, 'Junes' UNION ALL
SELECT 7, 'Julius' UNION ALL
SELECT 8, 'Augustus' UNION ALL
SELECT 9, 'Septembre' UNION ALL
SELECT 10, 'Ottobre' UNION ALL
SELECT 11, 'Novem' UNION ALL
SELECT 12, 'Decem'
;
-- Your query mapped against the view:
SELECT month_name AS rental_month, count(*) AS num_rentals
FROM rental
JOIN month_names ON idx = CAST(strftime('%m',rental_date) AS INTEGER)
WHERE rental_date BETWEEN '2005-05-01' AND '2005-08-01'
GROUP BY month_name
;
-- rental_month|num_rentals
-- ------------|---------
-- Augustus | 1
-- Julius | 1
-- Junes | 2
-- May | 3
(5) By anonymous on 2022-04-08 09:44:47 in reply to 4 [link] [source]
Thank you all. Very informative, but back to MySQL Workbench I go..
(6) By ET (EricTsau) on 2022-04-08 16:11:27 in reply to 4 [link] [source]
Hmm that doesn't seem to work for January?
sqlite> select trim(substr('-------January February March April May June July August SeptemberOctober November December', CAST( strftime('%m','2022-01-01') AS INTEGER) * 9, 9)) month;
month
anuary
(7) By Keith Medcalf (kmedcalf) on 2022-04-08 16:22:29 in reply to 6 [link] [source]
Add another '-' preceding January and another space before February.
This is called a fencepost error.
select value,
substr('--------January February March April May June July August SeptemberOctober November December', value * 9, 9)
from generate_series
where start=0 and stop=12;
┌───────┬──────────────────────────────────────────────────────────────┐
│ value │ substr('--------January February March April May │
├───────┼──────────────────────────────────────────────────────────────┤
│ 0 │ '--------' │
│ 1 │ 'January ' │
│ 2 │ 'February ' │
│ 3 │ 'March ' │
│ 4 │ 'April ' │
│ 5 │ 'May ' │
│ 6 │ 'June ' │
│ 7 │ 'July ' │
│ 8 │ 'August ' │
│ 9 │ 'September' │
│ 10 │ 'October ' │
│ 11 │ 'November ' │
│ 12 │ 'December' │
└───────┴──────────────────────────────────────────────────────────────┘
VM-steps: 120
Run Time: real 0.022 user 0.015625 sys 0.000000
sqlite>
(8) By ET (EricTsau) on 2022-04-08 16:27:51 in reply to 7 [source]
Add another '-' preceding January and another space before February.
Wonderful, that works, but I think you meant remove a space before February right?
(9.1) By Keith Medcalf (kmedcalf) on 2022-04-08 16:43:51 edited from 9.0 in reply to 8 [link] [source]
Yes.
On the gripping had, however, I would create a table containing the data and use a join operation (preferably a trailing LEFT JOIN) to get the name, allowing the Query Planner the freedom to not perform useless function calls to operationalize data which is intended for presentation and would simply substitute one value for another though complicated early transmorgification.
Of course, that depends on whether you consider a large dataset to mean tens of rows or billions of rows ... this is a case where early optimization should be applied.