Here's the table
*City Crime*
Bangkok High
Hongkong Very High
Seoul Low, Average
Texas Average, High
Jakarta Low
Singapore Very Low
Las Vegas Average, Low
how's the sql to search where the crime "Low"
i use the preg_split but i don't know to match the database
Use the LIKE matcher to select for a partial match on a string:
SELECT *
FROM cities
WHERE crime LIKE '%Low%'
If you need case insensitivity, use LOWER(crime) to convert the column to lowercase.
Try it.
Mysql:
SELECT *
FROM City
WHERE `Crime` REGEXP '^Low' or `Crime` REGEXP ', Low'
or `Crime` REGEXP 'Low,'
Sql:
select * from City
where (Crime like 'low%' or Crime like '%, low%' or Crime like '%low,%')
select *
from table
where
`crime` like '%Low%'
and `crime` not like '%Very Low%';
You select records where some criteria is met with WHERE.
select * from mytable where crime = 'Low';
There are further entries in your table where the crime string contains a 'Low' substring. E.g. 'Low, Average' and 'Average, Low'. I don't know the exact meaning of these, of course. Do both mean the same? Do they mean the crime is "low to avarage"? Or is it undecided whether "low or avarage"? And would you count this as "low" or would that be yet another level above "low"?
Then there is the entry 'Very Low'. Would you consider this "low" or a level beyond?
Depending on the answers you could extend above query to match all 'Low' substrings:
select * from mytable where crime like '%Low%';
Or use some more advanced string search, e.g.
select * from mytable
where ',' || replace(replace(crime, ', ', ','), ' ,', ',') || ',' like '%,Low,%';
which would get 'Low, Average' and 'Average, Low', but not 'Very Low'.
Related
I'm trying to run a query to select the distribution of a certain set of postcode areas in an addresses table. A postcode area is the section at the start of a UK postcode consisting of either 1 or 2 letters, which comes directly before the first numeric character.
In the WHERE clause, I have specified the postcode areas of interest (EC, WC, E, and W) by indicating the composition of the first 2 characters, however I also need to be able to group by postcode area, which is where I'm having difficulty. In the SELECT clause I'm trying to specify postcode areas by taking all the characters of a postcode that come before the first numeric character. You can see my attempt below, but the REGEXP '[0-9]' part doesn't work. Any suggestions as to how this can be achieved concisely? Thanks in anticipation!
SELECT LEFT(postcode, LOCATE(REGEXP '[0-9]', postcode) - 1) AS postcode_area, COUNT(*)
FROM addresses
WHERE LEFT(postcode, 2) REGEXP 'EC|WC|(E|W)[0-9]'
GROUP BY postcode_area
MySQL doesn't offer a "regular expression" substring operation. Perhaps the easiest way is to be explicit:
select left(postcode,
(case when substr(postcode, 2, 1) between '0' and '9' then 1
when substr(postcode, 3, 1) between '0' and '9' then 2
end)
) as postcode_area
You can put this into a query like this:
select left(postcode,
(case when substr(postcode, 2, 1) between '0' and '9' then 1
when substr(postcode, 3, 1) between '0' and '9' then 2
end)
) as postcode_area, count(*)
from addresses
group by postcode_area
having postcode_area in ('EC', 'WC', 'E', 'W');
I am not familiar with your use of locate and regexp.
I solved the problem shortly after posting, and just realised I didn't post my answer, so here it is:
SELECT LEFT(postal_code, IF(postal_code RLIKE '^[A-z][A-z]', 2, 1)) AS postcode_area, COUNT(*)
FROM addresses
GROUP BY postcode_area
HAVING postcode_area IN ('EC', 'WC', 'E', 'W')
I need to select all entries that do not start with a number between 1-9.
Example Entries:
6300 Dog Lane
Kitty Drive
500 Bird Chrest
800 Tire Road
Johnson Ave
Park Ave
So if I ran a query on the above, I would expect:
Kitty Drive
Johnson Ave
Park Ave
The table is called objects and the column is called location.
Something I tried:
SELECT DISTINCT name, location FROM object WHERE location NOT LIKE '1%' OR '2%' OR '3%' OR '4%' OR '5%' OR '6%' OR '7%' OR '8%' OR '9%';
Unfortunately, that is unsuccessful. Is this possible? If no, I will resort to modifying the data with Perl.
Try this:
SELECT DISTINCT name, location FROM object
WHERE substring(location, 1, 1)
NOT IN ('1','2','3','4','5','6','7','8','9');
or you have to add NOT LIKE before every number:
SELECT DISTINCT name, location FROM object
WHERE location NOT LIKE '1%'
OR location NOT LIKE '2%'
...
You can use the following stntax:
SELECT column FROM TABLE where column NOT REGEXP '^[0-9]+$' ;
SELECT DISTINCT name, location FROM object
WHERE location NOT REGEXP '^[0-9]+$' ;
Try this. It's simpler:
SELECT DISTINCT name, location FROM object WHERE location NOT LIKE '[0-9]%';
What you "tried" needed to have AND instead of OR. Also, DISTINCT is unnecessary.
If you have
INDEX(location)
this would probably be faster than any of the other answers:
( SELECT name, location FROM object
WHERE location < '1'
) UNION ALL
( SELECT name, location FROM object
WHERE location >= CHAR(ORD('9' + 1)) )
This technique only works for contiguous ranges of initial letters, such as 1..9.
A somewhat related question: Should I perform regex filtering in MySQL or PHP? -- it asks about fetching rows starting with 1..9 instead of the opposite.
Try this for SQL Server:
select column_name
from table
where substring(column_name,1,1) not in (1,2,3,4,5,6,7,8,9)
ISNUMERIC should work. (will exclude 0 as well).
Sample code -
ISNUMERIC(SUBSTRING(location, 1, 1)) = 0
I am writing a SQL query to select row, where a field with space separated numbers contains a single number, in this example the 1.
Example fields:
"1 2 3 4 5 11 12 21" - match, contains number one
"2 3 4 6 11 101" - no match, does not contain number one
The best query so far is:
$sql = "SELECT * from " . $table . " WHERE brands REGEXP '[/^1$/]' ORDER BY name ASC;";
Problem is that this REGEXP also finds 11 a match
I read many suggestions on other post, for instance [\d]{1}, but the result always is the same.
Is it possible to accomplish what I want, and how?
You don't need regex: You can use LIKE if you add a space to the front and back of the column:
SELECT * from $table
WHERE CONCAT(' ', brands, ' ') LIKE '% 1 %'
ORDER BY name
Try:
WHERE brands REGEXP '[[:<:]]1[[:>:]]'
[[:<:]] and [[:>:]] match word boundaries before and after a word.
Why not FIND_IN_SET() + REPLACE() ?
SELECT
*
FROM
`table`
WHERE
FIND_IN_SET(1, REPLACE(`brands`, ' ', ','))
ORDER BY
`name` ASC;
I recently set up a MYSQL database connected to a form filled with checkboxes. If the checkbox was selected, it would insert into the associated column a value of '1'; otherwise, it would receive a value of '0'.
I'd like to eventually look at aggregate data from this form, and was wondering if there was any way I could use MYSQL to get a number for each column which would be equal to the number of rows that had a value of '1'.
I've tried variations of:
select count(*) from POLLDATA group by column_name
which was unsuccessful, and nothing else I can think of seems to make sense (admittedly, I'm not all too experienced in SQL).
I'd really like to avoid:
select count(*) from POLLDATA where column_1='1'
for each column (there close to 100 of them).
Is there any way to do this besides typing out a select count(*) statement for each column?
EDIT:
If it helps, the columns are 'artist1', 'artist2', ....'artist88', 'gender', 'age', 'city', 'state'. As I tried to explain below, I was hoping that I'd be able to do something like:
select sum(EACH_COLUMN) from POLLDATA where gender='Male', city='New York City';
(obviously EACH_COLUMN is bogus)
SELECT SUM(CASE
WHEN t.your_column = '1' THEN 1
ELSE 0
END) AS OneCount,
SUM(CASE
WHEN t.your_column='0' THEN 1
ELSE 0
END) AS ZeroCount
FROM YOUR_TABLE t
If you are just looking for the sheer number of 1's in the columns, you could try…
select sum(col1), sum(col2), sum(col3) from POLLDATA
A slightly more compact notation is SUM( IF( expression ) ).
For the askers example, this could look something like:
select
count(*) as total,
sum(if(gender = 'MALE', 1, 0)) as males,
sum(if(gender = 'FEMALE', 1, 0)) as females,
sum(if(city = 'New York City', 1, 0)) as newYorkResidents
from POLLDATA;
Example result:
+-------+-------+---------+------------------+
| total | males | females | newYorkResidents |
+-------+-------+---------+------------------+
| 42 | 23 | 19 | 42 |
+-------+-------+---------+------------------+
select count(*) from POLLDATA group by column_name
I dont think you want to do a count cause this will also count the records with a 0.
try
select column_naam,sum(column_name) from POLLDATA group by column_name
or
select column_naam,count(*) from POLLDATA
where column_name <> 0
group by column_name
only adds the 0
Instead of strings why not store actual numbers, 1 or 0.
Then you could use the sql SUM function.
When the query begins to be a little too complicated, maybe it's because you should think again about your database structure. But if you want to keep your table as it is, you could use a prepared statement that automatically calculates all the sums for you, without specifying every single column:
SELECT
CONCAT(
'SELECT ',
GROUP_CONCAT(CONCAT('SUM(', `column_name`, ') AS sum_', `column_name`)),
' FROM POLLDATA WHERE gender=? AND city=?')
FROM `information_schema`.`columns`
WHERE `table_schema`=DATABASE()
AND `table_name`='POLLDATA'
AND `column_name` LIKE 'artist%'
INTO #sql;
SET #gender := 'male';
SET #city := 'New York';
PREPARE stmt FROM #sql;
EXECUTE stmt USING #gender, #city;
Please see fiddle here.
I've got a table of crime data. In a simplified version, it would look like this:
Table Headings:
crime_id, neighborhood, offense
Table Data:
- 1, Old Town, robbery
- 2, Bad Town, theft
- 3, Bad Town, theft
- 4, Uptown, stolen auto
If I SELECT * FROM mytable WHERE offense ='theft', then the results for Bad Town are returned. But, I'm making a ranking, so what I'm really interested in is:
Old Town: 0
Bad Town: theft
Bad Town: theft
Uptown: 0
How do I write a SELECT statement that returns cases where there are thefts, but also returns neighborhoods that don't have an entry for the specified offense?
UPDATE: This my actual SELECT. I'm having problems applying the solution that p.campbell and Gratzy were so kind to post to this SELECT. How do I apply the CASE statement with the COUNT(*)?
SELECT
cbn.neighborhoods AS neighborhoods,
COUNT(*) AS offenses,
TRUNCATE(((na.neighborhood_area_in_sq_meters /1000) * 0.000386102159),2) AS sq_miles,
( COUNT(*) / ((na.neighborhood_area_in_sq_meters /1000) * 0.000386102159) ) AS offenses_per_sq_mile
FROM
wp_crime_by_neighborhood cbn, wp_neighborhood_area na
WHERE
cbn.offense='theft'
AND
cbn.neighborhoods = na.neighborhoods
GROUP BY
cbn.neighborhoods
ORDER BY
offenses_per_sq_mile DESC
If you're looking to make a ranking, wouldn't it be better to get the number of thefts in Bad Town rather than a row for each? Something like this:
select distinct mt.neighborhood, ifnull(total, 0)
from mytable mt
left join (
select neighborhood, count(*) as total
from mytable
where offense = 'theft'
group by neighborhood
) as t on t.neighborhood = mt.neighborhood
Based on the data you gave, this query should return:
Old Town: 0
Bad Town: 2
Uptown: 0
That seems more useful to me for making a ranking. You can easily throw an order by on there.
I would think using a case statement should do it.
http://dev.mysql.com/doc/refman/5.0/en/case-statement.html
something like
Select neighborhood,
case offense when 'theft' then offense else '0' end case
from table
Try this:
SELECT cbn.neighborhoods AS neighborhoods,
CASE WHEN IFNULL(COUNT(*),0) > 0 THEN CONCAT(COUNT(*), ' ', offense)
ELSE '0'
END AS offenses
--- ... and the rest of your query
FROM wp_crime_by_neighborhood cbn
INNER JOIN wp_neighborhood_area na
ON cbn.neighborhoods = na.neighborhoods
WHERE cbn.offense='theft'
GROUP BY cbn.neighborhoods
--ORDER BY offenses_per_sq_mile DESC