How to iterate over possible values over values of a column - mysql

I have a table, which stores names and numbers associated with it. Each of these numbers are of a certain type. The combination of name and type is unique.
name | type | number
---------------------
a | t0 | 5
a | t1 | 6
b | t0 | 7
c | t1 | 8
And I want this table as a result, which shows the numbers which are associated with that name, regardless of type accumulated.
name | sum
------------
a | 11
c | 8
b | 7
Now I know the SUM() function and I have written this so far:
SELECT name, SUM( ??SELECT name, SUM(number) WHERE name = 'a'?? ) AS sum
FROM table
ORDER BY sum DESC;
The thing is I don't know how to write the inner part of the SUM() function, as I can't use SELECT statements inside of functions. Also I don't know how I can iterate over the possible values of the name column.

SELECT NAME,
Sum(number) As 'Sum'
FROM table
GROUP BY NAME
ORDER BY Sum(number) DESC;

You need to use GROUP BY along with SUM:
SELECT name, SUM(number) AS sum
FROM tableName
GROUP BY name
ORDER BY SUM(number) DESC; -- or ORDER BY sum DESC; - it is identical

Related

Operations with a created table MySQL [duplicate]

Here is a very basic look at my table. I have columns 1 and 2 and need to generate column 3. Column 3 is simply the total of the Number column for all Name divided by Number for the given row.
| Name | Number | % of total |
| ------------- |:-------------:| -----: |
| Bob | 5 | 25 |
| Sally | 10 | 50 |
| John | 5 | 25 |
I'm struggling with how to get the total of the number row and use this as a value to calculate the rest.
EDIT: I'm looking to do this as a single query instead of two separate if possible.
You just need to CROSS JOIN the SUM() of Number column:
SELECT Name, Number, Number * 100 / t.s AS `% of total`
FROM mytable
CROSS JOIN (SELECT SUM(Number) AS s FROM mytable) t
Demo Here
If I were doing this, I would start by storing a variable that held the total, like this:
SET #total := (SELECT SUM(number) FROM myTable);
Once I had that variable, I could run a query that got the percentage for each row like this:
SELECT name, number, (number / #total) * 100 AS percentage
FROM myTable;
If you don't want to use a variable, you can just move that subquery into your select statement:
SELECT name, number, (number / (SELECT SUM(number) FROM myTable)) * 100 AS percentage
FROM myTable;
Here is an SQL Fiddle example with each approach.
You can get it with a subselect:
SELECT Name, Number, Number * 100 / (select sum(Number) FROM MYTABLE) AS '% of total'
FROM mytable

Group by names desc - get last entered values for a grouped name

I have an table like that:
id | name | v (lvl)
11 | Jane | 6
12 | John | 5
13 | Jane | 6
14 | John | 5
15 | Jane | 7
16 | Jane | 5
In my autocomplete form now id like to group the names but get the last value (value with biggest id). In the example above would be
Jane | 5
I tried with combinations like distinct, group by, order by. But im always get
Jane | 6
or grouped like this and reversed:
Jane | 6
Jane | 7
Jane | 5
I would need something like this:
SELECT name,lvl FROM
(
SELECT DISTINCT name, lvl FROM pora WHERE name LIKE 'Jane' ORDER BY lvl DESC
)
GROUP BY name
EDIT: I won't get the highest lvl, i want get the lvl of the highest id, grouped by name. Thats all. My example above would be the best explanation what i like to get.
In the inner query i change the order to DESC for all and in the outer i group it by names. But i get an error for this.
EDIT 2 I finally did at my own. The correct solution (i was already close):
SELECT a.name, a.lvl FROM
(
SELECT DISTINCT name, lvl FROM pora WHERE name LIKE 'Jane' ORDER BY id DESC
)as a
GROUP BY name
LIKE without % is just =
SELECT *
FROM yourTable
WHERE name = 'Jane'
ORDER BY id DESC
LIMIT 1
But because you mention autocomplete functionality you should use:
WHERE name LIKE 'Jane%'
To have the latest, you need to have a field dateAdded which stores the date you ran the insert command.
Following which, you use MAX(dateAdded) to get the latest ID (since, as you mentioned, it may decrease as well)
UPDATE:
if ID doesn't decrease, you can always use MAX(ID)
SELECT MAX(id), v from tablename where name = 'Jane'
UPDATE:
This has been tested:
SELECT ID, v from tableName where ID = (SELECT MAX(ID) as ID from tableName where name like '%Jane%')
Try the following query (h/t #lamak)
WITH CTE AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY name
ORDER BY [id] DESC)
FROM poro
)
SELECT *
FROM CTE
WHERE RN = 1

MySQL Query Order by before Group By

name order_id
tom | 1 |
tom | 0 |
tom | 2 |
tom | 3 |
tom | 4 |
ken | 2 |
ken | 1 |
ken | 0 |
I have a table like above, how can I select the data group by the name and order by the order id. I already try the query below but it's not the result I want.
SELECT * FROM tbl_dummy GROUP BY name ORDER BY order_id ASC
This might be what you want:
SELECT name, MIN(order_id) AS order_id
FROM tbl_dummy
GROUP BY name
ORDER BY order_id
SELECT * FROM tbl_dummy GROUP by name,order_id order by name,order_id
For using GROUP BY clause, you must use some type of aggregate function (SUM, MIN, MAX ..) on all the other columns that you are selecting.
Try understand it this way, if you do group by name in the above data, then you will have two rows in the result, one for tom and one for ken. But what value of order_id should it display against each name? It cannot display all the values separated by comma (or anything else like that). The value to be shown must be a value calculated using all the values corresponding to that name. It could either be sum, average, min or max of all the values.
Ref: http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html
May be what you are looking for is to order your results by name first and then order_id in increasing order. In that case you can use order by multiple columns
SELECT name, order_id from yourtable order by name, order_id;

Get column sum and use to calculate percent of total (mySQL)

Here is a very basic look at my table. I have columns 1 and 2 and need to generate column 3. Column 3 is simply the total of the Number column for all Name divided by Number for the given row.
| Name | Number | % of total |
| ------------- |:-------------:| -----: |
| Bob | 5 | 25 |
| Sally | 10 | 50 |
| John | 5 | 25 |
I'm struggling with how to get the total of the number row and use this as a value to calculate the rest.
EDIT: I'm looking to do this as a single query instead of two separate if possible.
You just need to CROSS JOIN the SUM() of Number column:
SELECT Name, Number, Number * 100 / t.s AS `% of total`
FROM mytable
CROSS JOIN (SELECT SUM(Number) AS s FROM mytable) t
Demo Here
If I were doing this, I would start by storing a variable that held the total, like this:
SET #total := (SELECT SUM(number) FROM myTable);
Once I had that variable, I could run a query that got the percentage for each row like this:
SELECT name, number, (number / #total) * 100 AS percentage
FROM myTable;
If you don't want to use a variable, you can just move that subquery into your select statement:
SELECT name, number, (number / (SELECT SUM(number) FROM myTable)) * 100 AS percentage
FROM myTable;
Here is an SQL Fiddle example with each approach.
You can get it with a subselect:
SELECT Name, Number, Number * 100 / (select sum(Number) FROM MYTABLE) AS '% of total'
FROM mytable

MySQL - Exclude rows from Select based on duplication of two columns

I am attempting to narrow results of an existing complex query based on conditional matches on multiple columns within the returned data set. I'll attempt to simplify the data as much as possible here.
Assume that the following table structure represents the data that my existing complex query has already selected (here ordered by date):
+----+-----------+------+------------+
| id | remote_id | type | date |
+----+-----------+------+------------+
| 1 | 1 | A | 2011-01-01 |
| 3 | 1 | A | 2011-01-07 |
| 5 | 1 | B | 2011-01-07 |
| 4 | 1 | A | 2011-05-01 |
+----+-----------+------+------------+
I need to select from that data set based on the following criteria:
If the pairing of remote_id and type is unique to the set, return the row always
If the pairing of remote_id and type is not unique to the set, take the following action:
Of the sets of rows for which the pairing of remote_id and type are not unique, return only the single row for which date is greatest and still less than or equal to now.
So, if today is 2011-01-10, I'd like the data set returned to be:
+----+-----------+------+------------+
| id | remote_id | type | date |
+----+-----------+------+------------+
| 3 | 1 | A | 2011-01-07 |
| 5 | 1 | B | 2011-01-07 |
+----+-----------+------+------------+
For some reason I'm having no luck wrapping my head around this one. I suspect the answer lies in good application of group by, but I just can't grasp it. Any help is greatly appreciated!
/* Rows with exactly one date - always return regardless of when date occurs */
SELECT id, remote_id, type, date
FROM YourTable
GROUP BY remote_id, type
HAVING COUNT(*) = 1
UNION
/* Rows with more than one date - Return Max date <= NOW */
SELECT yt.id, yt.remote_id, yt.type, yt.date
FROM YourTable yt
INNER JOIN (SELECT remote_id, type, max(date) as maxdate
FROM YourTable
WHERE date <= DATE(NOW())
GROUP BY remote_id, type
HAVING COUNT(*) > 1) sq
ON yt.remote_id = sq.remote_id
AND yt.type = sq.type
AND yt.date = sq.maxdate
The group by clause groups all rows that have identical values of one or more columns together and returns one row in the result set for them. If you use aggregate functions (min, max, sum, avg etc.) that will be applied for each "group".
SELECT id, remote_id, type, max(date)
FROM blah
GROUP BY remote_id, date;
I'm not whore where today's date comes in, but assumed that was part of the complex query that you didn't describe and I assume isn't directly relevant to your question here.
Try this:
SELECT a.*
FROM table a INNER JOIN
(
select remote_id, type, MAX(date) date, COUNT(1) cnt from table
group by remote_id, type
) b
WHERE a.remote_id = b.remote_id,
AND a.type = b.type
AND a.date = b.date
AND ( (b.cnt = 1) OR (b.cnt>1 AND b.date <= DATE(NOW())))
Try this
select id, remote_id, type, MAX(date) from table
group by remote_id, type
Hey Carson! You could try using the "distinct" keyword on those two fields, and in a union you can use Count() along with group by and some operators to pull non-unique (greatest and less-than today) records!