Short question about the statement "group by" in mysql:
My current db structure looks like:
CREATE TABLE TableName
(
ID int primary key,
name varchar(255),
number varchar(255)
);
INSERT INTO TableName
(ID, name, number)
VALUES
(1, "Test 1", "100000"),
(2, "Apple", "200000"),
(3, "Test 1 beta", "100000"),
(4, "BLA", "300000"),
(5, "ABU", "400000"),
(6, "CBA", "700000"),
(7, "ABC", "600000"),
(8, "Orange - Test", "400000"),
(9, "ABC", "");
My current statement looks like:
SELECT name, number, count(*) as Anzahl
FROM TableName
group by name,number
with this statement the result looks like:
NAME NUMBER ANZAHL
ABC 1
Test 1 100000 2
Apple 200000 1
BLA 300000 1
ABU 400000 2
ABC 600000 1
CBA 700000 1
But the value "ABC" wouldn't merged.
the result should look like:
NAME NUMBER ANZAHL
Test 1 100000 2
Apple 200000 1
BLA 300000 1
ABU 400000 2
ABC 600000 2
CBA 700000 1
Any Ideas how it could work?
SQLFiddle:
http://sqlfiddle.com/#!2/dcbee/1
the solution must be performant for something like +1 000 000 rows
First of all IMHO, it's a bad design to store numbers into character column. Working with integers is faster than characters. Being said that, I assume all values in name column will be numbers. Here's is a query to avoid multiple ABC values
SELECT name,
SUM(convert(number, SIGNED INTEGER)) as number,
count(*) as Anzahl
FROM TableName
GROUP BY name ;
This is what I suggest (SQL Fiddle Link: http://sqlfiddle.com/#!2/c6f83b/5/0)
Like #Parag said, I strongly urge you to changed the table definition
Then the SQL is easy:
SELECT name, number, COUNT(*) AS anzahl
FROM tablename
WHERE number IS NOT NULL
GROUP BY name, number
Related
I want query in mysql to select a column values which contains Y and N.
Below is my table
If I use this query
"SELECT * from hotel where standard='Y' OR standard='N' group by hotel_code";
This query is working based on insert id but my requirement is not like that, first it should select 'Y' first then only 'N' should come.
[![enter image description here][3]][3]
I want select particular these column values
2 ---- 123 ------Y
4 -----324 ------Y
6 -----456 ------N or 5 ------456 -- N any row from when N appear
7 -----987 ------Y
Thanks in advance!!!
My previous answer has a problem which indicated error related to only_full_group_by when executing a query in MySql. However, I have created a local database myself and then came up with the correct sql that you need. Here it is.
SELECT min(origin), hotel_code, max(standard) as std from hotel
where standard='Y' OR standard='N'
group by hotel_code
order by std desc;
And after executing the sql, here's the result that I have got.
1 123 Y
3 324 Y
7 987 Y
5 456 N
I am sharing the create table and insert statements so that anyone can check by themselves if the query is okay.
create table hotel (
origin integer auto_increment primary key,
hotel_code integer not null,
standard varchar(1) not null
);
INSERT INTO `hotel` (`origin`, `hotel_code`, `standard`)
VALUES
(1, 123, 'Y'),
(2, 123, 'N'),
(3, 324, 'N'),
(4, 324, 'Y'),
(5, 456, 'N'),
(6, 456, 'N'),
(7, 987, 'N'),
(8, 987, 'Y');
Hope that helps!
Here what you need:
SELECT origin, hotel_code, CASE COUNT(DISTINCT standart)
WHEN 1 AND standart = "N" THEN "N"
WHEN 1 AND standart = "Y" THEN "Y"
WHEN 2 THEN "Y"
END as standart
FROM hotel
GROUP BY hotel_code ORDER BY standart DESC
Results:
origin hotel_code standart
1 123 Y
3 324 Y
9 888 Y
7 987 Y
6 456 N
SQLFiddle: http://sqlfiddle.com/#!9/17bd53/3/0
There are many approaches to solve your algorithm, however, due to simplicity I pick this one:
SELECT h2.origin, h2.hotel_code, h2.standard
FROM (SELECT * FROM hotel WHERE standard = 'Y') h1
JOIN hotel h2 on h1.hotel_code = h2.hotel_code
ORDER BY h2.hotel_code, h2.standard;
Click here to view it working
Enjoy it!
I am running a query that currently counts species from animals table. However I am not getting the desired result with the query listed below. Currently the COUNT is counting number of specie, which is composed of two words type and breed(e.g. dog-pitbull). The query returns 1 for all entries. However, How could I group result and count by dogs,cats,birds, etc. disregarding breed? SQLFIDDLE
Query
SELECT specie, COUNT(*) as Total FROM animals GROUP BY specie;
Schema
CREATE TABLE animals
(`id` int, `name` varchar(20), `specie` varchar(55))
;
INSERT INTO animals
(`id`, `name`, `specie`)
VALUES
(1, 'dougie', 'dog-poodle'),
(2, 'bonzo', 'dog-pitbull'),
(3, 'cadi', 'cat-persian'),
(4, 'mr.turtle', 'turtle-snapping'),
(5, 'spotty', 'turtle-spotted'),
(6, 'tweety', 'bird-canary')
;
This query will give you the animal type and the count i.e. 2 dog, 1 cat, 2 turtle, 1 bird.
It looks at the value of specie and it return the value before the 1st - found along with the count.
SELECT
SUBSTRING_INDEX(specie,'-',1) AS specie
, COUNT(*) AS total
FROM animals
GROUP BY SUBSTRING_INDEX(specie,'-',1);
USE SUBSTRING_INDEX:
SELECT SUBSTRING_INDEX(specie,'-',1), specie, COUNT(*) AS Total
FROM animals GROUP BY SUBSTRING_INDEX(specie,'-',1);
RESULT:
bird bird-canary 1
cat cat-persian 1
dog dog-poodle 2
turtle turtle-snapping 2
DOKU SUBSTRING_INDEX
I just cannot seem to find an answer for this deceptively simple question. Most every solution either deletes all the duplicates, selects all the duplicates, or selects all the records except the duplicates. How can I select all rows such that, in this example, the "name" column values are unique, while selecting the first record of any duplicate set and ignoring the remaining duplicates of that same name? I do need all the values from all the columns in all the records in the selected record set.
Given the set of records:
pk fk name secs note
1 100 cat 90 gray
2 111 dog 123 mix
3 233 fish 75 gold
4 334 dog 932 black
5 238 cow 90 stray
6 285 cat 90 stray
The returned set should be:
pk fk name secs note
1 100 cat 90 gray
2 111 dog 123 mix
3 233 fish 75 gold
5 238 cow 90 stray
-- SQL
drop table if exists foo;
create table foo (
pk int unsigned,
fk int unsigned,
name varchar(10),
secs int,
note varchar(10),
primary key (pk)
) engine=innodb default charset=utf8;
insert into foo
(pk, fk, name, secs, note)
values
(1, 100, 'cat', 90, 'gray'),
(2, 111, 'dog', 123, 'mix'),
(3, 233, 'fish', 75, 'gold'),
(4, 334, 'dog', 932, 'black'),
(5, 238, 'cow', 90, 'stray'),
(6, 285, 'cat', 90, 'stray');
Here is a query that that returns what you're looking for:
SELECT
F.*
FROM
foo F
INNER JOIN
( SELECT
MIN(F2.pk) AS `pk`
,F2.name
FROM foo F2
GROUP BY F2.name
) T
ON T.pk = F.pk;
Hope this will help you.
I think you are looking for this :
select * from table group by name;
Which can be written using distinct keyword as :
select distinct on name * from table;
In SQL it will be
select pk, fk, name, secs, note
from (select row_number()
over(partition by name order by pk) as rn,*
from foo) as tbl
where rn=1
So I have a weird scenario where I want the following data to be ordered in a certain way. Let the table data be:
abc 111 2 priority
abc 111 blah data
abc 222 1 priority
abc 222 blah data
abc 333 3 priority
abc 333 blah data
I want to order that data based on column three (where column 4 is priority) but keep the return order grouped by column 2. So the expected query result would look like:
abc 222 1 priority
abc 222 blah data
abc 111 2 priority
abc 111 blah data
abc 333 3 priority
abc 333 blah data
What's the best possible way of doing this. I can think of doing a query up front and an in clause, but then I would have to account for all possible priorities.
Thanks in advance. FYI, its MySQL that I am using.
I think this is what you need:
http://sqlfiddle.com/#!2/48057/14
DDL
CREATE TABLE my_data(
name VARCHAR(20),
num NUMERIC(5),
c NUMERIC(3),
priority NUMERIC(3)
);
DML
INSERT INTO my_data VALUES("abc", 111, 2, 1);
INSERT INTO my_data VALUES("abc", 222, 3, 4);
INSERT INTO my_data VALUES("abc", 222, 1, 9);
INSERT INTO my_data VALUES("abc", 111, 4, 2);
It would be better if you could have actually include actual column names even with bogus data, however, I've named them corresponding with the type of content I think you are presenting.
It appears your second column is some "ID" column and want to keep them all grouped together. So, pre-query that in the order you want but only for the "Priority" column ignoring the rest of the records. THEN, using MySQL variables, you can assign it a sequential value for final output. Then join to the regular data on the "ID" column for all other values... Something like...
select
md2.ABCColumn,
SortSeqQuery.IDColumn,
md2.DescripColumn,
md2.ColumnWith123Sequence
from
my_Data md2
LEFT JOIN ( select
md1.IDColumn,
#SeqVal := #SeqVal +1 as FinalSortOrder
from
my_Data md1,
( select #SeqVal := 0 ) sqlvars
where
md1.DescripColumn = "priority"
order by
md1.ColumnWith123Sequence,
md1.IDColumn ) SortSeqQuery
on md2.IDColumn = SortSeqQuery.IDColumn
order by
case when SortSeqQuery.IDColumn is null then 2 else 1 end,
coalesce( SortSeqQuery.FinalSortOrder, 0 ) as FinalSort
With the "Order By", it pre-sorts the qualified data BEFORE it actually applies the #SeqVal which in turn should come back as 1, 2, 3, 4, etc...
The "SortSeqQuery" will be run first to pre-qualify any "priority" records and have them sorted and available. Then, your "my_data" table is basis of the query and joins to that result set and grabs the appropriate sort sequence based on matching ID column. If there are IDColumn entries that DO NOT have a priority, then they will also be included, but with the order by based on a case/when, any that are null are pre-sorted to the bottom, those found will be sorted to the top. Within that sort, it will keep all IDColumn entries grouped together since the same "FinalSortOrder" is directly associated to the IDColumn in the preliminary query.
ANSWER -
CREATE TABLE my_data( name VARCHAR(20),groupid INT(5), attributekey VARCHAR(10),attributevalue VARCHAR(10));
INSERT INTO my_data VALUES("abc", 111, "priority", "2");
INSERT INTO my_data VALUES("abc", 111, "someattr", "blah");
INSERT INTO my_data VALUES("abc", 222, "priority", "1");
INSERT INTO my_data VALUES("abc", 222, "someattr", "blah");
INSERT INTO my_data VALUES("abc", 333, "priority", "3");
INSERT INTO my_data VALUES("abc", 333, "someattr", "blah");
solution -
SELECT m1.*,
(select attributevalue from my_data m2
where m1.groupid=m2.groupid
AND m2.attributekey='priority'
) groupidpriority
FROM my_data m1
order by groupidpriority;
My knowledge of MySQL is basic. I want to build a query to return all rows that sum a given value, in ascending order. I can't figure out how I can do that. Using sum() only returns one row. I've tried a subquery but it returns all rows. I don't want anybody do my work, I just want you to help me to figuring this out.
Anybody have an idea?
How to retrieve all rows that its filed "value" sum 30
Example:
given value: 30
field to sum: value
table:
id name value order
1 name1 3 1
2 name2 10 6
3 name3 13 3
4 name4 5 8
5 name5 20 25
So, the query must return:
id 1, id 3, id 2, id 4
Thanks in advance.
set #total:=0;
select id, name, value, `order`
from
(select
id, name, value, `order`,
#total:=if(#total is null, 0, #total)+`order` as total
from THE_TABLE
order by `order`
) as derived
where total<=30;
Using postgres as database, I think this does what you want. I'm not sure if it works similar in mysql:
CREATE TABLE test (
id int,
name varchar(50),
value int,
order_ int
);
INSERT INTO test values (1, 'name1', 3, 1);
INSERT INTO test values (3, 'name3', 13, 3);
INSERT INTO test values (2, 'name2', 10, 6);
INSERT INTO test values (4, 'name4', 5, 8);
INSERT INTO test values (5, 'name5', 20, 25);
SELECT * FROM (SELECT *, SUM(value) OVER (ORDER BY order_) sumvalues FROM TEST) a WHERE sumvalues <30