Problem with renaming a field in sql table - mysql

So i have this table:
SELECT * FROM table LIMIT 10;
+----+----------------+------------+----------+----------------+--------+--------+
| sex_id | First name | year of beginning | year of ending | country | | |
+----+----------------+------------+----------+----------------+--------+--------+
| 56| mimic | 1987 | NULL | United Kingdom | Group | NULL |
| 3 | charales glass | 1941 | NULL | United States | Person | Male |
| 33| Grass | 1983 | 2000 | United Kingdom | Group | NULL |
| 67| Mother | 1989 | 2000 | United States | Group | NULL |
| 69| wind of lollie | 1950 | NULL | United States | Person | Male |
+----+----------------+------------+----------+----------------+--------+--------+
‎‎‎‎‎‎‎
‎‎‎‎‎‎‎‎‎‎
‎‎‎
‎‎‎
I t‎‎‎‎hen make the ‎‎‎table smaller to show what i want to rename which is the end year, and i want to change it to NULL.
‎‎‎‎‎ERROR 1366 (HY000): Incorrect integer value 'NULL' for column 'end_year' at row 155

Please remove quotes from 'NULL' in your update statement.
UPDATE table_name SET row_name=NULL WHERE name='Specific name';

NULL not equal varchar2,so you should try end_year=NULL

Related

finding distinct pairs in sql

I was trying to learn non-equi joins when I encountered this problem. I have a table pops:
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| country | varchar(100) | YES | | NULL | |
| continent | varchar(100) | YES | | NULL | |
| population | bigint(20) | YES | | NULL | |
I was trying to find countries with their population in the vicinity of say, 100.
select distinct
p1.country,
p2.country,
p1.population,
p2.population
from pops p1
inner join pops p2
on p1.population between p2.population - 100 and p2.population + 100
and p1.country <> p2.country
where p2.country <> p1.country
output I got was:
+------------+------------+------------+------------+
| country | country | population | population |
+------------+------------+------------+------------+
| pakistan | india | 99988 | 99999 |
| china | india | 99990 | 99999 |
| bangladesh | japan | 999 | 999 |
| india | pakistan | 99999 | 99988 |
| china | pakistan | 99990 | 99988 |
| japan | bangladesh | 999 | 999 |
| india | china | 99999 | 99990 |
| pakistan | china | 99988 | 99990 |
+------------+------------+------------+------------+
as we can see, I am getting pairs of (india, pakistan) as well as (pakistan, india), which is data-wise the same thing. Is it possible to eliminate one of the records from the pair?
You could decide to always have the lexographically first (or last, for argument's sake) country on the p1 side - use < (or >) instead of <>.
Also, note that your where clause is redundant, since you already have this condition in the on clause of the join:
select p1.country,
p2.country,
p1.population,
p2.population
from pops p1
inner join pops p2
on p1.population between p2.population - 100 and p2.population + 100 and
p1.country < p2.country
-- Here ------------------^
just change the join condition of p1.country <> p2.country to p1.country < p2.country

Sort result with empty strings first

I have this locations table:
+----+-----------+------------+----------+
| id | country | state | city |
+----+-----------+------------+----------+
| 1 | US | Georgia | Atlanta |
| 2 | US | California | |
| 3 | US | | |
| 4 | Canada | Ontario | |
| 5 | Canada | Manitoba | Winnipeg |
| 6 | Canada | | |
I want to create a query but could not build my ORDER BY properly. This is the result that I want:
+----+-----------+------------+----------+
| id | country | state | city |
+----+-----------+------------+----------+
| 6 | Canada | | |
| 3 | US | | |
| 4 | Canada | Ontario | |
| 2 | US | California | |
| 5 | Canada | Manitoba | Winnipeg |
| 1 | US | Georgia | Atlanta |
Basically, this is the priority that I want to follow:
Country listing. Alphabetical order.
State listing. Alphabetical order.
City listing. Alphabetical order.
This query does not seem to account for empty columns (I am not using NULLs in my locations table):
SELECT * FROM locations
ORDER BY
country,state,city
Try this ORDER BY clause:
SELECT *
FROM locations
ORDER BY
CASE WHEN state = '' AND city = '' THEN 0
WHEN city = '' THEN 1
ELSE 2 END,
country,
state,
city;
This sorting logic places first those records which are missing both state and city. Next follows records missing city only, followed last by records having non empty data for all three fields.
For versions pre 8.0...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,country VARCHAR(20) NOT NULL
,state VARCHAR(20) NULL
,city VARCHAR(20) NULL
);
INSERT INTO my_table VALUES
(1,'US','Georgia','Atlanta'),
(2,'US','California',NULL),
(3,'US',NULL,NULL),
(4,'Canada','Ontario',NULL),
(5,'Canada','Manitoba','Winnipeg'),
(6,'Canada',NULL,NULL);
SELECT id
, country
, state
, city
FROM
( SELECT x.*
, CASE WHEN #prev=country THEN #i:=#i+1 ELSE #i:=1 END i
, #prev:=country
FROM my_table x
, (SELECT #prev:=null,#i:=0) vars
ORDER
BY country
, city
, state
) a
ORDER
BY i
, country;
+----+---------+------------+----------+
| id | country | state | city |
+----+---------+------------+----------+
| 6 | Canada | NULL | NULL |
| 3 | US | NULL | NULL |
| 4 | Canada | Ontario | NULL |
| 2 | US | California | NULL |
| 5 | Canada | Manitoba | Winnipeg |
| 1 | US | Georgia | Atlanta |
+----+---------+------------+----------+
select *
from locations
order by
state <> '',
city <> '',
country,
state,
city
db-fiddle
Note that in MySQL a boolean expression returns 0 (for FALSE) or 1 (for TRUE). That means for an empty state string state <> '' will return 0 and thus ordered first.

mySql Mistakes with the wrong symbol: is it a Tic, Comma, or Quotations?

I am using the wrong syntax. It's confusing as a beginner to get mixed up with using the comma, quotation and the tic mark.
-list the form of government for the countries with the top 5 average GNP.
Here is the statement that I am using and the results.
SELECT 'avg-gnp','form-government'
FROM country
ORDER BY 'avg-gnp'
DESC LIMIT 5;
+---------+-----------------+
| avg-gnp | form-government |
+---------+-----------------+
| avg-gnp | form-government |
| avg-gnp | form-government |
| avg-gnp | form-government |
| avg-gnp | form-government |
| avg-gnp | form-government |
+---------+-----------------+
5 rows in set (0.01 sec)
I've also tried this: Thanks in advance!
mysql> SELECT * FROM country ORDER BY 'avg-GNP' DESC LIMIT 5;
+------+-------------+---------------+---------------------------+--------+-------------------+------------+--------------+---------+----------------------------------------------+
| code | fullname | continent | region | area | year-independence | population | avg-lifespan | avg-GNP | form-government |
+------+-------------+---------------+---------------------------+--------+-------------------+------------+--------------+---------+----------------------------------------------+
| ABW | Aruba | North America | Caribbean | 193 | 0 | 103000 | 78.40 | 828.00 | Nonmetropolitan Territory of The Netherlands |
| AFG | Afghanistan | Asia | Southern and Central Asia | 652090 | 1919 | 22720000 | 45.90 | 5976.00 | Islamic Emirate |
| AGO | Angola | Africa | Central Africa | 124670 | 1975 | 12878000 | 38.30 | 6648.00 | Republic |
| AIA | Anguilla | North America | Caribbean | 96 | 0 | 8000 | 76.10 | 63.20 | Dependent Territory of the UK |
| ALB | Albania | Europe | Southern Europe | 28748 | 1912 | 3401200 | 71.60 | 3205.00 | Republic |
+------+-------------+---------------+---------------------------+--------+-------------------+------------+--------------+---------+----------------------------------------------+
5 rows in set (0.00 sec)
This is a comment that cannot be put in a comment since comments don't allow back ticks. I wanted to make sure you got it right.
Correct Form (this is how it should look using back ticks):
SELECT `avg-gnp`,`form-government`
FROM country
ORDER BY `avg-gnp`
DESC LIMIT 5;
Wrong Form (this is the way you had it using single quotes):
SELECT 'avg-gnp','form-government'
FROM country
ORDER BY 'avg-gnp'
DESC LIMIT 5;
Do you see the difference?
And yes, MySQL is weird about this. The only database I know that uses back ticks (well... and MariaDB, of course).

Finding MySQL near-duplicates across two columns using wildcards

I have a table with id, first_name and last_name columns. I'd like to get a listing of rows where last_name and the first character of first_name are duplicated. I am groping my way around and have a sense that there is a COUNT('WHERE') in there, but can't quite get to it.
In essence, I'm looking for possible duplicates. So, from this subset:
+------+-----------+-----------+-------------+------------+
| id | firstName | lastName | dateOfBirth | createdOn |
+------+-----------+-----------+-------------+------------+
| 143 | Susie | Wong | 2015-12-01 | 2016-07-11 |
| 1268 | Dale | Armstrong | 2017-01-01 | 2017-01-04 |
| 1435 | Olive | Armstrong | 1941-03-11 | 2017-03-08 |
| 2013 | Timotini | Attilio | 1932-01-01 | 2017-08-21 |
| 2014 | Olinda | Attilio | 1938-01-01 | 2017-08-21 |
| 3076 | Sue | Armstrong | 1951-06-01 | 2018-06-22 |
| 3079 | Susan | Armstrong | 1951-09-15 | 2018-06-22 |
+------+-----------+-----------+-------------+------------+
I would like a query that returns only 3076 and 3079 (Sue and Susan Armstrong) based on looking for a matching last name and a matching first initial, like so:
+------+-----------+-----------+-------------+------------+
| id | firstName | lastName | dateOfBirth | createdOn |
+------+-----------+-----------+-------------+------------+
| 3076 | Sue | Armstrong | 1951-06-01 | 2018-06-22 |
| 3079 | Susan | Armstrong | 1951-09-15 | 2018-06-22 |
+------+-----------+-----------+-------------+------------+
Here's one option using exists and left:
select *
from yourtable y
where exists (
select 1
from yourtable y2
where y.id != y2.id
and y.lastname = y2.lastname
and left(y.firstname,1) = left(y2.firstname,1)
)
Sample Fiddle Demo
Duplicates of last_name
SELECT id, first_name, last_name, COUNT(*) c
FROM table
GROUP BY last_name
HAVING c > 1;
For grouping by the first character in first_name, try playing with left() function

Mysql query - Count items grouping by year and including "sub-counts"

I have a table "events" like this
id | user_id | date | is_important
---------------------------------------------------
1 | 3 | 01/02/2012 | 0
1 | 3 | 01/02/2012 | 1
1 | 3 | 01/02/2011 | 1
1 | 3 | 01/02/2011 | 1
1 | 3 | 01/02/2011 | 0
Basically, what I need to get is this:
(for the user_id=3)
year | count | count_importants
--------------------------------------------
2012 | 2 | 1
2011 | 3 | 2
I've tried this:
SELECT YEAR(e1.date) as year,COUNT(e1.id) as count_total, aux.count_importants
FROM events e1
LEFT JOIN
(
SELECT YEAR(e2.date) as year2,COUNT(e2.id) as count_importants
FROM `events` e2
WHERE e2.user_id=18
AND e2.is_important = 1
GROUP BY year2
) AS aux ON aux.year2 = e1.year
WHERE e1.user_id=18
GROUP BY year
But mysql gives me an error
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'aux ON aux.year2 = e1.year WHERE e1.user_id=18 GROUP BY year LIMIT 0, 30' at line 10
And i've run out of ideas to make this query u_Uº. Is it possible to do this using only one query??
Thanks in advance
Edit: I think I over-complicated things. Can't you just do this in a simple query?
SELECT
YEAR(`year`) AS `year`,
COUNT(`id`) AS `count`,
SUM(`is_important`) AS `count_importants`
FROM `events`
WHERE user_id = 18
GROUP BY YEAR(`year`)
Here's the big solution that adds summaries :)
Consider using MySQL GROUP BY ROLLUP. This will basically do a similar job to a normal GROUP BY, but will add rows for the summaries too.
In the example below, you see two records for Finland in 2000, for £1500 and £100, and then a row with the NULL product with the combined value of £1600. It also adds NULL rollup rows for each dimension grouped by.
From the manual:
SELECT year, country, product, SUM(profit)
FROM sales
GROUP BY year, country, product WITH ROLLUP
+------+---------+------------+-------------+
| year | country | product | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | Finland | NULL | 1600 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
| 2000 | India | NULL | 1350 |
| 2000 | USA | Calculator | 75 |
| 2000 | USA | Computer | 1500 |
| 2000 | USA | NULL | 1575 |
| 2000 | NULL | NULL | 4525 |
| 2001 | Finland | Phone | 10 |
| 2001 | Finland | NULL | 10 |
| 2001 | USA | Calculator | 50 |
| 2001 | USA | Computer | 2700 |
| 2001 | USA | TV | 250 |
| 2001 | USA | NULL | 3000 |
| 2001 | NULL | NULL | 3010 |
| NULL | NULL | NULL | 7535 |
+------+---------+------------+-------------+
Here's an example the specifically matches your situation:
SELECT year(`date`) AS `year`, COUNT(`id`) AS `count`, SUM(`is_important`) AS `count_importants`
FROM new_table
GROUP BY year(`date`) WITH ROLLUP;
The alias year - year(e1.date) AS year is not visible in JOIN ON clause. Try to use this condition -
...
LEFT JOIN
(
...
) ON aux.year2 = year(e1.date) -- e1.year --> year(e1.date)
...