Mysql query: combine two queries - sql

Below is an over-simplified version of table I'm using:
fruits
+-------+---------+
| id | type |
+-------+---------+
| 1 | apple |
| 2 | orange |
| 3 | banana |
| 4 | apple |
| 5 | apple |
| 6 | apple |
| 7 | orange |
| 8 | apple |
| 9 | apple |
| 10 | banana |
+-------+---------+
Following are the two queries of interest:
SELECT * FROM fruits WHERE type='apple' LIMIT 2;
SELECT COUNT(*) AS total FROM fruits WHERE type='apple'; // output 6
I want to combine these two queries so that the results looks like this:
+-------+---------+---------+
| id | type | total |
+-------+---------+---------+
| 1 | apple | 6 |
| 4 | apple | 6 |
+-------+---------+---------+
The output has to be limited to 2 records but it should also contain the total number of records of the type apple.
How can this be done with 1 query?

SELECT *, (SELECT COUNT(*) AS total FROM fruits WHERE type='apple') AS Total
FROM fruits WHERE type='apple' LIMIT 2;
Depending on how MySQL interprets it, it may cache the inner query so that it doesn't have to reevaluate it for every record.
Another way to do it is with a nested query and a join (this would be useful it you need more than one fruit type, for example):
SELECT fruits.*, counts.total
FROM fruits
INNER JOIN (SELECT type, COUNT(*) AS total FROM fruits GROUP BY type) counts ON (fruits.type = counts.type)
WHERE fruits.type='apple'
LIMIT 2;

You should use SQL_CALC_FOUND_ROWS for that.
SELECT SQL_CALC_FOUND_ROWS * FROM fruits WHERE type='apple' LIMIT 2;
will return the IDs of your apples, and remember how much it would have returned without the LIMIT clause
SELECT FOUND_ROWS();
will return how many apples would have been found, without the limit statement.

Related

Counting and presenting only duplicates

So I have a table like this:
Name | Fruit | price
----------------------
Effy | Apple| 8
Effy | Banana | 9
Alam | Apple | 8
Alam | Banana | 10
Boji | Apple | 11
Suppose I want to get rid only from the Names that has one value (like Boji). How can I do it in big Query?
I thought to add HAVING clause and to add Having count(*) > 2, since this table is already grouped by,
but i's no working the way I want.
Select Distinct name, fruit, price from fruit_db
group by name, fruit
output:
Name | Fruit | price
----------------------
Effy | Apple| 8
Effy | Banana | 9
Alam | Apple | 8
Alam | Banana | 10
Try below
select * except(qualified) from (
select *,
count(1) over(partition by name) > 1 qualified
from `project.dataset.table`
)
where qualified
if applied to sample data in your question - output is

Make a query making groups on the same result row

I have two tables. Like this.
select * from extrafieldvalues;
+----------------------------+
| id | value | type | idItem |
+----------------------------+
| 1 | 100 | 1 | 10 |
| 2 | 150 | 2 | 10 |
| 3 | 101 | 1 | 11 |
| 4 | 90 | 2 | 11 |
+----------------------------+
select * from items
+------------+
| id | name |
+------------+
| 10 | foo |
| 11 | bar |
+------------+
I need to make a query and get something like this:
+--------------------------------------+
| idItem | valtype1 | valtype2 | name |
+--------------------------------------+
| 10 | 100 | 150 | foo |
| 11 | 101 | 90 | bar |
+--------------------------------------+
The quantity of types of extra field values is variable, but every item ALWAYS uses every extra field.
If you have only two fields, then left join is an option for this:
select i.*, efv1.value as value_1, efv2.value as value_2
from items i left join
extrafieldvalues efv1
on efv1.iditem = i.id and
efv1.type = 1 left join
extrafieldvalues efv2
on efv1.iditem = i.id and
efv1.type = 2 ;
In terms of performance, two joins are probably faster than an aggregation -- and it makes it easier to bring in more columns from items. One the other hand, conditional aggregation generalizes more easily and the performance changes by little as more columns from extrafieldvalues are added to the select.
Use conditional aggregation
select iditem,
max(case when type=1 then value end) as valtype1,
max(case when type=2 then value end) as valtype2,name
from extrafieldvalues a inner join items b on a.iditem=b.id
group by iditem,name

How to select values, where each one depends on a previously aggregated state?

I have the following table:
|-----|-----|
| i d | val |
|-----|-----|
| 1 | 1 |
|-----|-----|
| 2 | 4 |
|-----|-----|
| 3 | 3 |
|-----|-----|
| 4 | 7 |
|-----|-----|
Can I get the following output:
|-----|
| sum |
|-----|
| 1 |
|-----|
| 5 |
|-----|
| 8 |
|-----|
| 1 5 |
|-----|
using a single SQLite3 SELECT-query? I know it could be easily achieved using variables, but SQLite3 lacks those. Maybe some recursive query? Thanks.
No.
In a relational database table rows do not have any order. If you specify an order for the rows, then it's possible to write a query.
Now, you could add an extra column to sort the rows. For example:
| val | sort
|-----|-----
| 1 | 10
| 4 | 20
| 3 | 30
| 7 | 40
The query could be:
select
sum(val) over(order by sort)
from my_table
For the updated question, you can write:
select
sum(val) over(order by id)
from my_table
By using the order of the id column and if you want only the sum column, you can do this:
select (select sum(val) from tablename where id <= t.id) sum
from tablename t

Applying distinct in multiple columns in SQL server

I am trying to get distinct result by only one column( message). I tried
SELECT DISTINCT
[id], [message]
FROM Example table
GROUP BY [message]
But it doesn't show desired result.
Please let me know how can I do it?
Example table:
id | Message |
-- ------------
1 | mike |
2 | mike |
3 | star |
4 | star |
5 | star |
6 | sky |
7 | sky |
8 | sky |
Result table:
id | Message |
-- ------------
1 | mike |
3 | star |
6 | sky |
Group by the column you want to be unique and use an aggregate function on the other column. You want the lowest id for every message, so use MIN()
select min(id) as id,
message
from your_table
group by message

SQL Group by one column and decide which column to choose

Let's say I have data like this :
| id | code | name | number |
-----------------------------------------------
| 1 | 20 | A | 10 |
| 2 | 20 | B | 20 |
| 3 | 10 | C | 30 |
| 4 | 10 | D | 80 |
I would like to group rows by code value, but get real rows back (not some aggregate function).
I know that just
select *
from table
group by code
won't work because database don't know which row to return where code is the same.
So my question is how to tell database to select (for example) the lower number column so in my case
| id | code | name | number |
-----------------------------------------------
| 1 | 20 | A | 10 |
| 3 | 10 | C | 30 |
P.S.
I know how to do this by PARTITION but this is only allowed in Oracle databases and can't be created in JPA criteria builder (what is my ultimate goal).
Why You don't use code like this?
SELECT
id,
code,
name,
number
FROM
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY code ORDER BY number ASC) AS RowNo
FROM table
) s
WHERE s.RowNo = 1
You can look at this site;
Data Partitioning