Fetch first character of each word in sqlite3 string - sqlite

In sqlite3 table we have names like as below.
Monty Python
Luther Blissett
Rey maR EsteBaN
Monty Cantsin
Geoffrey Cohen
Karen Eliot
Poor Konrad
I need a query to fetch the character from the database.
Initially I need a query that should fetch first letter of every word in a string. In above example it should display M, P, L, B, R, E, C, G, K
Suppose if a user selects C after the above query, then it should fetch next possible characters of Cantsin and Cohen i.e A and O.
Please provide any inputs on how the solution can be arrived?

Solution below would work if only first name is taken to count.
Consider data:
sqlite> SELECT name FROM COMPANY;
Paul Allen
Mark
Monty Python
Luther Blissett
Monty Cantsin
For 1st query:
sqlite> SELECT distinct substr(name,1,1) FROM COMPANY;
P
M
L
And later for 2nd output try below algorithm:
if you have 1 character input then use substr (name, 2,1)
if you have 2 characters input then use substr (name, 3,1)
.. generally : if x is number of characters input and y is number of character output expected, try substr (name, x+1, y)
sqlite> SELECT distinct substr(name,2,1) FROM COMPANY where name like 'M%';
a
o
sqlite> SELECT distinct substr(name,3,1) FROM COMPANY where name like 'Ma%';
r
If others words also need to be considered for search, replace table name with sub queries as below.
SELECT distinct substr(name,2,1) FROM
(
select name from company where name like 'A%' -- counts for first word
UNION
select name from company where name like '% A%' -- counts for words that start with space
);
Please note that above queries will only return the characters of first word, though the match is for all words it would consider first name as source to fetch characters.

Related

SELECT the matching condition value along with the result from a multiple condition WHERE clause on the same column

I think this is a pretty simple question but I can't figure out the right search terms to search this. This question is the most similar I could find, but it's the opposite of what I'm trying to do.
I have a query like this :
SELECT * FROM table WHERE column LIKE "val1%" OR column LIKE "val2%" OR column LIKE "val3%", ...so..on..and..on
Since it's an OR, only some of them will give matches from the column.
How can I return the matching LIKE clause with the query itself ? Like this :
SELECT *, (val1 or val2 or val3 - the matched val) FROM table WHERE column LIKE "val1%" OR column LIKE "val2%" OR column LIKE "val3%", ...so..on..and..on
Since the matching is by wildcard "%", I need to get the exact value that got the match.
If the table is this :
name
age
Mike
1
John
2
Michael
3
Milinda
4
And if the query is :
SELECT *, (the matched value) FROM table WHERE name LIKE "Mik%" OR name LIKE "Mic%" OR name LIKE "mia%"
It would return :
name
age
match
Mike
1
Mik
Michael
3
Mic
Is this possible purely with an SQLite query ? I know this can be done later after obtaining the results, but want to remove that redundancy since SQLite will already be matching anyway.
Note: The table is very large. 100,000+ rows. So performance is a big factor to get result as fast as possible. Also the OR conditions can be 5 or 10 or 15+
Create a CTE with all the match strings that you have and join to the table:
WITH cte(match) AS (VALUES ('Mik'), ('Mic'))
SELECT t.*, c.match
FROM tablename t INNER JOIN cte c
ON t.name LIKE c.match || '%'
See the demo.
You may use a case expresssion. See working fiddle below:
Schema (SQLite v3.30)
CREATE TABLE my_table (
`name` VARCHAR(7),
`age` INTEGER
);
INSERT INTO my_table
(`name`, `age`)
VALUES
('Mike', '1'),
('John', '2'),
('Michael', '3'),
('Milinda', '4');
Query #1
SELECT
*,
CASE
WHEN name LIKE "Mik%" THEN "Mik"
WHEN name LIKE "Mic%" THEN "Mic"
WHEN name LIKE "mia%" THEN "mia"
END as matched_value
FROM
my_table
WHERE
name LIKE "Mik%" OR
name LIKE "Mic%" OR
name LIKE "mia%";
name
age
matched_value
Mike
1
Mik
Michael
3
Mic
View on DB Fiddle

How to get the total quantity of results using count(*)?

i need to get the total quantity of results for each person but i get ...
resultado
MY QUERY..
select t.fecha_hora_timbre,e.nombre,e.apellido,d.descripcion as departamento_trabaja, t.fecha,count(*)
from fulltime.timbre t, fulltime.empleado e, fulltime.departamento d
where d.depa_id=e.depa_id and t.codigo_empleado=e.codigo_empleado and
trunc(t.fecha) between trunc(to_date('15/02/2017','dd/mm/yyyy')) and trunc(to_date('14/03/2017','dd/mm/yyyy'))
group by t.fecha_hora_timbre,e.nombre,e.apellido,d.descripcion, t.fecha
Expected data...
NOMBRE | APELLIDO | DEPARTAMENTO_TRABAJA | VECES_MARCADAS(count)
MARIA TARCILA IGLESIAS BECERRA ALCALDIA 4
KATHERINE TATIANA SEGOVIA FERNANDEZ ALCALDIA 10
FREDDY AGUSTIN VALDIVIESO VALLEJO ALCALDIA 3
UPDATE..
select e.nombre,e.apellido,d.descripcion as departamento_trabaja,COUNT(*)
from fulltime.timbre t, fulltime.empleado e, fulltime.departamento d
where d.depa_id=e.depa_id and t.codigo_empleado=e.codigo_empleado and
trunc(t.fecha) between trunc(to_date('15/02/2017','dd/mm/yyyy')) and trunc(to_date('14/03/2017','dd/mm/yyyy'))
group by t.fecha_hora_timbre,e.nombre,e.apellido,d.descripcion, t.fecha
You should only select and group by the non-aggregate columns you actually want to count against. At the moment you're including the fecha_hora_timbre and fechacolumns in each row, so you're counting the unique combinations of those columns as well as the name/department information you actually want to count.
select e.nombre, e.apellido, d.descripcion as departamento_trabaja,
count(*) a veces_marcadas
from fulltime.timbre t
join fulltime.empleado e on t.codigo_empleado=e.codigo_empleado
join fulltime.departamento d on d.depa_id=e.depa_id
where t.fecha >= to_date('15/02/2017','dd/mm/yyyy')
and t.fecha < to_date('15/03/2017','dd/mm/yyyy')
group by e.nombre, e.apellido, d.descripcion
I've removed the extra columns. Notice that they have gone from both the select list and the group-by clause. If you have a non-aggregate column in the select list that isn't in the group-by you'll get an ORA-00937 error; but if you have a column in the group-by that isn't in the select list then it will still group by that even though you can't see it and you just won't get the results you expect.
I've also changed from old-style join syntax to modern syntax. And I've changed the date comparison; firstly because doing trunc() as part of trunc(to_date('15/02/2017','dd/mm/yyyy')) is pointless - you already know the time part is midnight, so the trunc doesn't achieve anything. But mostly so that if there is an index on fecha that index can be used. If you do trunc(f.techa) then the value of every column value has to be truncated, which stops the index being used (unless you have a function-based index). As between in inclusive, using >= and < with one day later on the higher limit should have the same effect overall.

A-Z loop in SQL Stored Procedure

For a project, I have to loop through the alphabet and run a search for each letter against some values in a database. The function would return the number of matches for each letter.
I would like to be able to do this in a SQL Stored Procedure, but I'm not certain how I could do a 'FOR letter = A to Z' loop in a SP. Does anyone know how this could be done?
it depends according to alphabet if you only need English characters you can do a loop from 65 (ascii for A) and 90 (Z) and use char letter = (char)i to get the letter.
If you also need non-English ones just set a web config setting "ABC......Z" and loop through it.
with ATable(c) as
(
select cast('A' as CHAR(1)) as c
union all
select CHAR(ASCII(c)+1) as C from ATable where C<'Z'
)
select * from ATable
SQLFiddle demo
Use a loop going from 65 (A) to 90 (Z), and use the T-SQL CHAR() function.
Of course, I'm assuming that you are using a SQL Server database. If not, please post the DB you're using.
You need to use "group by" and possibly include "count" in the query too. you can find further information here http://msdn.microsoft.com/en-us/library/ms177673.aspx
;WITH Alphabet AS
(
SELECT CHAR(65) AS Letter, 65 AS Code
UNION ALL
SELECT CHAR(Code + 1), Code + 1
FROM Alphabet
WHERE Code < 90
)
SELECT Letter
FROM Alphabet
WITH alpha AS
(
SELECT 65 AS c
UNION ALL
SELECT c + 1 FROM alpha
WHERE c < 90
)
SELECT CHAR(c) FROM alpha

Oracle - Use of Between with letters - Between 'A' and 'C'

this doubt is very basic, however, after reading an answer for a given question I got fairly confused (I don't know why as it is a simple subject).
Consider this basic query:
SELECT * FROM emp WHERE ename BETWEEN ‘A’ AND ‘C’
The employees name returned will be those whose names start with A and B, and the explanation is as follows:
Here, a character column is compared against a string using the
BETWEEN operator, which is equivalent to ename >= ‘A’ AND ename <=
‘C’. The name CLARK will not be included in this query, because
‘CLARK’ is > ‘C’.
Why is Clark considered greater than 'C' if in the explanation we have the statement: ename is less than or equal to 'C' ?
Thank you.
Because when you alphabetically sort
Constant Clark C Claude
you'll get
C Clark Claude Constant
so
C < Clark < Claude < Constant
See Wikipedia for a more formal explanation, the essence is this (emphasis mine):
To decide which of two strings comes first in alphabetical order,
initially their first letters are compared. The string whose first
letter appears earlier in the alphabet comes first in alphabetical
order. If the first letters are the same, then the second letters are
compared, and so on, until the order is decided. (If one string runs
out of letters to compare, then it is deemed to come first; for
example, "cart" comes before "carthorse".) The result of arranging a
set of strings in alphabetical order is that words with the same first
letter are grouped together, and within such a group words with the
same first two letters are grouped together and so on.
Why is Clark considered greater than 'C' if in the explanation we have the statement: ename is less than or equal to 'C' ?
There is one thing to consider here.For obvious reasons we have ALLEN,BLAKE,CLARK,ADAMS,A,C.Sorting alphabetically we have
A
ADAMS
ALLEN
BLAKE
C
CLARK
That's why CLARK IS NOT PART OF THE RANGE BECAUSE IT COMES AFTER C.

SQLite returns single row even though I am not using GROUP BY

I have the following SQLite database
I expect there will be 3 rows of result being returned, if I make the following query.
SELECT name, sum(heart) FROM test_table;
However, even though I am not using GROUP BY, only 1 row is being returned.
C:\Users\yan-cheng.cheok\Desktop>sqlite3.exe
SQLite version 3.7.13 2012-06-11 02:05:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .restore abc
sqlite> SELECT name, sum(heart) FROM test_table;
Record3|102
I am expecting result :
Record1|102
Record2|102
Record3|102
As in convientional SQL, if I do not use GROUP BY, every individual rows will be returned.
http://www.w3schools.com/sql/sql_groupby.asp
Is there anything I can make all 3 rows returned?
Try this you can use cross join
SELECT a.name, b.totalHeart
FROM test_table a,
(
SELECT SUM(heart) totalHeart
FROM test_table
) b
This behaviour is documented:
If the SELECT statement is an aggregate query without a GROUP BY clause, then each aggregate expression in the result-set is evaluated once across the entire dataset. Each non-aggregate expression in the result-set is evaluated once for an arbitrarily selected row of the dataset. The same arbitrarily selected row is used for each non-aggregate expression. Or, if the dataset contains zero rows, then each non-aggregate expression is evaluated against a row consisting entirely of NULL values.
You could do this:
sqlite> select a.name, b.s from abc as a, (select sum(heart) as s from abc) as b;
Record1|102
Record2|102
Record3|102

Resources