I have a column state that have values like
california
IL
north Carolina
TX
Dc
mixed values abbr and full names
and doing search with like using full state names
how do I convert abbr to full name and do like search based on full names all in lowercase
Man, this data need urgent normalization!
If normalization is not possible, I devised a fiddle with a possible solution here: http://sqlfiddle.com/#!9/cf3ef0/1
Given a dummy table
create table Dummy(
id int,
state varchar(255)
);
insert into Dummy values(1, 'AL');
insert into Dummy values(2, 'Alabama');
insert into Dummy values(3, 'Alaska');
To look for data given state like '%ala%', the query shall be:
select *
from
Dummy
inner join us_states
on(
us_states.code = Dummy.state
or us_states.name = Dummy.state
)
where us_states.name like '%ala%'
Given the pre-existing table with all us_states:
create table us_states(
code varchar(2),
name varchar(255)
);
insert into us_states
select *
from
(
select 'AL' as code, 'Alabama' as name union all
select 'AK' as code, 'Alaska' as name union all
select 'AS' as code, 'American Samoa' as name union all
select 'AZ' as code, 'Arizona' as name union all
select 'AR' as code, 'Arkansas' as name union all
select 'CA' as code, 'California' as name union all
select 'CO' as code, 'Colorado' as name union all
select 'CT' as code, 'Connecticut' as name union all
select 'DE' as code, 'Delaware' as name union all
select 'DC' as code, 'District of Columbia' as name union all
select 'FM' as code, 'Federated States of Micronesia' as name union all
select 'FL' as code, 'Florida' as name union all
select 'GA' as code, 'Georgia' as name union all
select 'GU' as code, 'Guam' as name union all
select 'HI' as code, 'Hawaii' as name union all
select 'ID' as code, 'Idaho' as name union all
select 'IL' as code, 'Illinois' as name union all
select 'IN' as code, 'Indiana' as name union all
select 'IA' as code, 'Iowa' as name union all
select 'KS' as code, 'Kansas' as name union all
select 'KY' as code, 'Kentucky' as name union all
select 'LA' as code, 'Louisiana' as name union all
select 'ME' as code, 'Maine' as name union all
select 'MH' as code, 'Marshall Islands' as name union all
select 'MD' as code, 'Maryland' as name union all
select 'MA' as code, 'Massachusetts' as name union all
select 'MI' as code, 'Michigan' as name union all
select 'MN' as code, 'Minnesota' as name union all
select 'MS' as code, 'Mississippi' as name union all
select 'MO' as code, 'Missouri' as name union all
select 'MT' as code, 'Montana' as name union all
select 'NE' as code, 'Nebraska' as name union all
select 'NV' as code, 'Nevada' as name union all
select 'NH' as code, 'New Hampshire' as name union all
select 'NJ' as code, 'New Jersey' as name union all
select 'NM' as code, 'New Mexico' as name union all
select 'NY' as code, 'New York' as name union all
select 'NC' as code, 'North Carolina' as name union all
select 'ND' as code, 'North Dakota' as name union all
select 'MP' as code, 'Northern Mariana Islands' as name union all
select 'OH' as code, 'Ohio' as name union all
select 'OK' as code, 'Oklahoma' as name union all
select 'OR' as code, 'Oregon' as name union all
select 'PW' as code, 'Palau' as name union all
select 'PA' as code, 'Pennsylvania' as name union all
select 'PR' as code, 'Puerto Rico' as name union all
select 'RI' as code, 'Rhode Island' as name union all
select 'SC' as code, 'South Carolina' as name union all
select 'SD' as code, 'South Dakota' as name union all
select 'TN' as code, 'Tennessee' as name union all
select 'TX' as code, 'Texas' as name union all
select 'UT' as code, 'Utah' as name union all
select 'VT' as code, 'Vermont' as name union all
select 'VI' as code, 'Virgin Islands' as name union all
select 'VA' as code, 'Virginia' as name union all
select 'WA' as code, 'Washington' as name union all
select 'WV' as code, 'West Virginia' as name union all
select 'WI' as code, 'Wisconsin' as name union all
select 'WY' as code, 'Wyoming' as name
) states;
Related
create table mpr (
name nvarchar(50),
value nvarchar(50)
);
insert mpr
select 'Name','Ravi' Union all
select 'Gender','M' Union all
select 'Salary','38162' Union all
select 'Name','Sundar' Union all
select 'Gender','M' Union all
select 'Salary','34932' Union all
select 'Name','Jayesh' Union all
select 'Gender','M' Union all
select 'Salary','37224' Union all
select 'Name','Murali' Union all
select 'Gender','M' Union all
select 'Salary','43482' Union all
select 'Name','Priya' Union all
select 'Gender','F' Union all
select 'Salary','44831' Union all
select 'Name','Sandhya' Union all
select 'Gender','F' Union all
select 'Salary','26694' Union all
select 'Name','Karthik' Union all
select 'Gender','M' Union all
select 'Salary','36336' Union all
select 'Name','Premna' Union all
select 'Gender','F' Union all
select 'Salary','33432';
select * from mpr
I want output as metioned below
[enter image description here][1]
[1]: https://i.stack.imgur.com/W3amD.png
select
case when name = 'Name' then value end as 'Name',
case when name = 'Gender' then value end as 'Gender',
case when name = 'Salary' then value end as 'Salary'
from mpr
Thank you.
Your table is missing a primary key column which uniquely identifies each user. Assuming that such an id column exist, we can try a pivot query here:
SELECT id,
MAX(CASE WHEN name = 'Name' THEN value END) AS name,
MAX(CASE WHEN name = 'Gender' THEN value END) AS gender,
MAX(CASE WHEN name = 'Salary' THEN value END) AS salary
FROM mpr
GROUP BY id;
I have 2 tables: _divions and _employee. In _employee there's a column division which is id_division in the table _division. I need to order them by the _division order first.
This table has a column order. I have tried this SQL statement, but it doesn't do much:
SELECT
e . *
FROM
`_employee` AS `e`
JOIN
`_division` AS d
ORDER BY
d.order,
e.division,
e.order
You missing ON clause. Try this
SELECT e.*
FROM _employee AS e
JOIN _division AS d ON d.id_division = e.division
// ^^^^ Missing
ORDER BY e.order
Below query may help. (Assuming there are divisions with no employees)
with employee as
(
select 'NISHA' ENAME, '10' EDIV FROM DUAL
UNION
SELECT 'ABC' ENAME, '10' EDIV FROM DUAL
UNION
SELECT 'DEF' ENAME, '15' EDIV FROM DUAL
UNION
SELECT 'GHI' ENAME, '20' EDIV FROM DUAL
),
DIVISION AS
(
SELECT '10' DIV_ID, 'INFO-TECH' DIV_DESC FROM DUAL
UNION
SELECT '15' DIV_ID, 'HUMAN RESOURCES' DIV_DESC FROM DUAL
UNION
SELECT '20' DIV_ID, 'SALES' DIV_DESC FROM DUAL
UNION
SELECT '25' DIV_ID, 'RESEARCH' DIV_DESC FROM DUAL
)
SELECT *
FROM EMPLOYEE, DIVISION WHERE
employee.EDIV (+) = DIVISION.DIV_ID
ORDER BY DIV_DESC, ENAME
If all employees would definitely have a division,then use employee.EDIV = DIVISION.DIV_ID instead of employee.EDIV (+) = DIVISION.DIV_ID
Is there any way I can change this SQL so the terms are defined only once?
SQLFiddle.
SELECT sum(score) score, title
FROM
(
SELECT
score,
title
FROM
(
SELECT 3 score, 'a railway employee' term UNION ALL
SELECT 2 score, 'a railway' term UNION ALL
SELECT 2 score, 'railway employee' term UNION ALL
SELECT 1 score, 'a' term UNION ALL
SELECT 1 score, 'railway' term UNION ALL
SELECT 1 score, 'employee' term
) terms
INNER JOIN tableName ON title LIKE concat('%', terms.term, '%')
UNION ALL
SELECT
score*1.1 score,
title
FROM
(
SELECT 3 score, 'a railway employee' term UNION ALL
SELECT 2 score, 'a railway' term UNION ALL
SELECT 2 score, 'railway employee' term UNION ALL
SELECT 1 score, 'a' term UNION ALL
SELECT 1 score, 'railway' term UNION ALL
SELECT 1 score, 'employee' term
) terms
INNER JOIN tableName ON summary LIKE concat('%', terms.term, '%')
) AS t
GROUP BY title
ORDER BY score DESC
If you don't want to write them out twice, why not just create a table that stores the terms and the scores and then you join on the table:
create table terms
(
term varchar(50),
score int
);
insert into terms values
('a railway employee', 3),
('a railway', 2),
('railway employee', 2),
('a', 1),
('railway', 1),
('employee', 1);
Then the query will be:
SELECT sum(score) score, title
FROM
(
SELECT score,title
FROM terms
INNER JOIN tableName ON title LIKE concat('%', terms.term, '%')
UNION ALL
SELECT score*1.1 score, title
FROM terms
INNER JOIN tableName ON summary LIKE concat('%', terms.term, '%')
) AS t
GROUP BY title
ORDER BY score DESC;
See SQL Fiddle with Demo
Note: I do advise that you put the values into their own table. Just sticking them in the query text is probably not ideal. But the queries I present below will work equally well with a real table as with a hard-coded derived table.
Here's one way:
SELECT
sum(score * multiplier) score,
title
FROM
(
SELECT 3 score, 'a railway employee' term UNION ALL
SELECT 2, 'a railway' UNION ALL
SELECT 2, 'railway employee' UNION ALL
SELECT 1, 'a' UNION ALL
SELECT 1, 'railway' UNION ALL
SELECT 1, 'employee'
) terms
CROSS JOIN (
SELECT 'title' which, 1 multiplier
UNION ALL SELECT 'summary', 1.1
) X
INNER JOIN tableName ON
CASE
X.which WHEN 'title' THEN title
WHEN 'summary' THEN summary
END
LIKE concat('%', terms.term, '%')
GROUP BY title
ORDER BY score DESC
;
See a Live Demo at SQL Fiddle
And here's another way that is basically the same but shuffled around a little bit:
SELECT
sum(terms.score * T.multiplier) score,
title
FROM
(
SELECT 3 score, 'a railway employee' term UNION ALL
SELECT 2, 'a railway' UNION ALL
SELECT 2, 'railway employee' UNION ALL
SELECT 1, 'a' UNION ALL
SELECT 1, 'railway' UNION ALL
SELECT 1, 'employee'
) terms
INNER JOIN (
SELECT
title,
CASE
X.which WHEN 'title' THEN title
WHEN 'summary' THEN summary
END comparison,
X.multiplier
FROM
tableName
CROSS JOIN (
SELECT 'title' which, 1 multiplier
UNION ALL SELECT 'summary', 1.1
) X
) T ON T.comparison LIKE concat('%', terms.term, '%')
GROUP BY title
ORDER BY score DESC
;
See a Live Demo at SQL Fiddle
And finally, one more way:
SELECT *
FROM
(
SELECT
sum(
terms.score * (
CASE WHEN T.title LIKE concat('%', terms.term, '%') THEN 1 ELSE 0 END
+ CASE WHEN T.summary LIKE concat('%', terms.term, '%') THEN 1.1 ELSE 0 END
)
) score,
title
FROM
tableName T
CROSS JOIN (
SELECT 3 score, 'a railway employee' term UNION ALL
SELECT 2, 'a railway' UNION ALL
SELECT 2, 'railway employee' UNION ALL
SELECT 1, 'a' UNION ALL
SELECT 1, 'railway' UNION ALL
SELECT 1, 'employee'
) terms
GROUP BY title
ORDER BY score DESC
) Z
WHERE
Z.score > 0
;
See a Live Demo at SQL Fiddle
Also, if MySQL has something like CROSS APPLY that will let the CROSS JOIN have an outer reference, then some of this becomes easier (e.g., the first query could lose the CASE statement completely).
Maybe I don't understand the question...dinner...wine...etc ... but can you use multiple columns?
select animal, score + score2 as combinedScore
from
(
select 'cat' as animal, 1 as score, 1 * 1.1 as score2
union
select 'dog' as animal, 2 as score, 2 * 2.2 as score2
) as X
Say I have the following:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age FROM (
SELECT name, age FROM clubAmembers
UNION
SELECT name, age FROM clubBmembers
)
) AS atable
How can I make it such that I can "stick in a new row at the beginning of the table" prior to the SELECT union such that it would start with:
rownum | name| age
1 | "Jordan" | 6 <-- This is an arbitrarily inserted record with name="Jordan" age="6" that is not a part of any of the clubAmembers or clubBmembers table.
The rest of the table (rownum 2 and onwards) would contain the actual result form the union with clubAmembers then clubBmembers.
Basically I am looking for:
CREATE TABLE
INSERT a row "Jordan" | 6
Perform select with union such that the rows after the first would start with "rownum=2", all the data from clubAmembers, etc.
How to best do this?
"At the beginning of the table" is not truly meaningful to relational databases because the order results are returned are not guaranteed until you use an ORDER BY clause, at which point the order on disk becomes a moot point anyway.
In your case, since you want to guarantee an order in your result clause (and therefore ordering #rownum, you will have to use ORDER BY. Something like:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age
FROM (
SELECT 'Jordan' AS name, 6 AS age, 0 AS ord
UNION
SELECT name, age, 1 AS ord FROM clubAmembers
UNION
SELECT name, age, 1 AS ord FROM clubBmembers
ORDER BY ord
)
) AS atable
Note that at no point does this guarantee that rows in clubAmembers will have a lower rownum than rows in clubBmembers. If you want to guarantee that clubAmembers have a lower rownum, while keeping the semantics of UNION (versus UNION ALL), you can use the following:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age
FROM (
SELECT 'Jordan' AS name, 6 AS age, 0 AS ord
UNION ALL
SELECT name, age, 1 AS ord FROM clubAmembers
UNION ALL
SELECT name, age, 2 AS ord FROM clubBmembers AS b
WHERE NOT EXISTS(SELECT 1 FROM clubAmembers AS a
WHERE a.name = b.name AND a.age = b.age)
ORDER BY ord
)
) AS atable
Note if {name, age} could be duplicated within the clubXmembers table, you will need to add DISTINCT:
...
SELECT DISTINCT name, age, 1 AS ord FROM clubAmembers
UNION ALL
...
As per the request in the comments, if you had a clubCmembers table, you would do:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age
FROM (
SELECT 'Jordan' AS name, 6 AS age, 0 AS ord
UNION ALL
SELECT name, age, 1 AS ord FROM clubAmembers
UNION ALL
SELECT name, age, 2 AS ord FROM clubBmembers AS b
WHERE NOT EXISTS(SELECT 1 FROM clubAmembers AS a
WHERE a.name = b.name AND a.age = b.age)
SELECT name, age, 3 AS ord FROM clubCmembers AS c
WHERE NOT EXISTS(SELECT 1 FROM clubAmembers AS a
WHERE a.name = c.name AND a.age = c.age)
AND NOT EXISTS(SELECT 1 FROM clubBmembers AS b
WHERE b.name = c.name AND b.age = c.age)
ORDER BY ord
)
) AS atable
I'm not sure if I got it right. But why don't you just add another union like this:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age FROM (
SELECT 1, "Jordan", 6
UNION ALL
SELECT name, age FROM clubAmembers
UNION ALL
SELECT name, age FROM clubBmembers
)
) AS atable
You can separate the create table statmenet from the insert statmenet:
Create the table (you must know which colums are gona be there)
Insert your 1st record (INSERT INTO .... Values(...))
Use your statement but with insert into instead of create table like: INSERT INTO YourNewTable.... Values(YourSubQuery) (Nr and tye of columns must match your subquery)
This should do, I believe:
CREATE TABLE newtable AS (
SELECT (#rownum:=IFNULL(#rownum,0)+1)+1 as rownum, name, age FROM (
SELECT name, age FROM clubAmembers
UNION
SELECT name, age FROM clubBmembers
) AS s
UNION ALL
SELECT 1, 'Jordan', 6
) AS atable
Demo at SQL Fiddle: http://sqlfiddle.com/#!2/ab825/6
People
here is my little problem.
I have three table:
a_names_1
b_names_2
c_names_3
they are same by structure. all of them has two item: name and used
Is there any QUERY to run to get and count all the 'name' that has 'used'=1 from all those three tables together.
I've tried this one, but didn't work:
(SELECT COUNT(*) 'name' from a_names_1) UNION
(SELECT COUNT(*) 'name' from a_names_2) UNION
(SELECT COUNT(*) 'name' from a_names_3) WHERE `used`=1
I'm using PHPMyAdmin for MySQL.
Any Help would be appreciated.. thanks in advance
This query outputs count of distinct names from all tables with used=1
select count(distinct name)
from
(
select name,used from a_names_1 where used=1
union all
select name,used from a_names_2 where used=1
union all
select name,used from a_names_3 where used=1
) t
If you need to SUM all USED for each NAME from all tables and output only with SUM of used=1 then:
select count(*) from
(
select name, SUM(used)
from
(
select name,used from a_names_1
union all
select name,used from a_names_2
union all
select name,used from a_names_3
) t
GROUP BY name
HAVING SUM(used)=1
) t1
select count(*) as name
from
(
select name, used from a_names_1
union
select name, used from a_names_2
union
select name, used from a_names_3) t
where t.used = 1
Probably this is slow, because you lose the index optimizations. What I would do is do the three queries, something like
SELECT SUM('name') AS name_sum
FROM ((SELECT COUNT(*) 'name' from a_names_1 WHERE `used`=1)
UNION (SELECT COUNT(*) 'name' from a_names_2 WHERE `used`=1));
If this doesn't work, it is probably a problem with the usage of name
Maybe you wanted this way:
select count(*) as cnt
from
(
select name from a_names_1 t1 where t1.used = 1
union
select name from a_names_2 t2 where t2.used = 1
union
select name from a_names_3 t3 where t3.used = 1
) t
The straight forward solution;
SELECT SUM(used) FROM (
SELECT used FROM a_names_1 WHERE used=1
UNION ALL
SELECT used FROM a_names_2 WHERE used=1
UNION ALL
SELECT used FROM a_names_3 WHERE used=1
) a
SQLfiddle for testing
An alternative if you have an index on used (and the only values of used are 0 or 1) is to just do the counting using the index;
SELECT SUM(used) total FROM (
SELECT SUM(used) used FROM a_names_1
UNION ALL
SELECT SUM(used) FROM a_names_2
UNION ALL
SELECT SUM(used) FROM a_names_3
) a
SQLfiddle for this example.
If you look at the query plan of the latter query, you can see it uses the indexes effectively.