most frequent observation or median of a set - sql-server-2008

I am aggregating data and I cannot sum certain columns so I would like to take the most frequent observation from that column, or the median value. Example follows, thanks in advance.
ID site
1 3
1 3
1 2
1 3
2 4
2 5
2 5
2 5
I want it to look like
ID Site
1 3
2 5

WITH temp AS(
SELECT ID, Site, COUNT(*) As counts
FROM id_table
GROUP BY ID, Site
)
SELECT temp.ID, temp.Site
FROM temp
JOIN (SELECT ID, MAX(counts) max_counts
FROM temp
GROUP BY ID
)b
ON temp.ID = b.ID
AND temp.counts = b.max_counts
ORDER BY ID ASC
SQL Fiddle

Related

MySQL query for selecting multiple rows as arrays of those rows data

Is there a way to select frist 3 rows and after that next 3 ( offset 3 ) and get the result as two arrays in a single query ? Something like:
(SELECT * FROM product WHERE 1 LIMIT 3) as first_array
(SELECT * FROM product WHERE 1 OFFSET 3 LIMIT 3) as second_array
Hope you understand me. Sorry about the explanation just dont't know how to explain in other way.
Lets say I only want the ids - output example:
id_1 id_2
1 4
2 5
3 6
What I have tried from the answers below the post is :
SELECT id as id_1 FROM `ct_product` WHERE 1 LIMIT 3
UNION ALL
SELECT id as id_2 FROM `ct_product` WHERE 1 LIMIT 3 OFFSET 3
The result is strange for me. It seems it returns only the second query results and they are not the 4th 5th and 6th row but the 5th 6th and 3th (in this order).
My table rows are:
id
1
2
3
4
5
6
7
You could do it with this query:
SELECT a1.id, a2.id
FROM (SELECT *, #rownum1:=#rownum1+1 AS rownum
FROM (SELECT id
FROM `ct_product`
LIMIT 3
) art
JOIN (SELECT #rownum1 := 0) r
) a1
JOIN (SELECT *, #rownum2:=#rownum2+1 AS rownum
FROM (SELECT id
FROM `ct_product`
LIMIT 3, 3
) art
JOIN (SELECT #rownum2 := 0) r
) a2
ON a1.rownum = a2.rownum
Output:
id id
1 4
2 5
3 6
This query works by creating two new tables with artificially generated row numbers (#rownum1 and #rownum2) from the first 3 and the second 3 rows in the original table. They are then JOINed on matching row numbers to get the desired result.

MYSQL - having count(*) without group by

I have a MySQL table
discount_vouchers
------------------
id
email
test_id
My goal is to list all vouchers that appears more than once with a given email and a given test_id from the GROUP BY:
GROUP BY email, test_id
HAVING count(*) >1
How to get read of this group by?
Here is an example:
discount_vouchers
------------------
1 1#test.com 20
2 1#test.com 10
3 1#test.com 20
4 2#test.com 30
I would like to have as a result:
id email test_id count
1 1#test.com 20 2
2 1#test.com 10 1
3 1#test.com 20 2
4 2#test.com 30 2
Try something like the following
SELECT C2, counter from
(SELECT C2, COUNT(*) as counter FROM test.mytable
GROUP BY C2) as aggregation
WHERE counter > 1
Without using group by, you can do something like
SELECT a.* ,
(SELECT count(*) FROM discount_vouchers b
WHERE a.email = b.email AND a.test_id = b.test_id) as count
FROM discount_vouchers a
How about this?
Aggregate using a subquery, and use its results in order to enrich the actual table:
SELECT `discount_vouchers`.*, `counts`.`count`
FROM `discount_vouchers`
INNER JOIN (SELECT `email`, `test_id`, Count(*) AS 'count'
FROM `discount_vouchers`) AS `counts`
ON `discount_vouchers`.`email` = `counts`.`email`
AND `discount_vouchers`.`test_id` = `counts`.`test_id`;

Select the first 5 rows and get count

I'm trying to write a mysql query:
first select 5 rows and then get count with a where
first select 5 rows
table
id user_id
--------
1 1
2 2
3 3
4 1
5 1
6 4
7 3
8 1
id user_id
----------
1 1
2 2
3 3
4 1
5 1
And then get count this table where user_id =1
result = 3
You can try somthing like that
Select count(*) From
(Select * From T
order by ID asc Limit 5) as child
where user_id = 1
Looks like you want to present two different result sets together. You need to use a JOIN for this. Something like so will do the trick for you.
SELECT T.*,c.cnt
FROM T
JOIN ( SELECT COUNT(*) cnt FROM T where user_id = 1 ) c
LIMIT 5
The subquery generates your count as a one-row resultset, and the JOIN (which lacks an ON condition) puts it into every row of your other resultset.
If you wanted to show five rows from your table, and have each row mention the count for the userid in that row, you could do this.
SELECT T.*,c.cnt
FROM T
JOIN ( SELECT COUNT(*) cnt, user_id
FROM T
GROUP BY user_id
) c ON T.user_id = c.user_id
LIMIT 5
The way that summary (COUNT(), etc) queries and detail queries work together is a little intricate, but you will figure it out.
Beware, though: If you do a LIMIT without first doing an ORDER BY, MySQL is free to return any five rows it pleases.

Query: getting the last record for each member trouble cause by another value

i have data below for example
id product_id date
------ ---------- ----
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2
6 2 2
7 3 1
result data query that i want "the last record of last date on each product_id"
to get it that result i use the query like below
SELECT a.* FROM test AS a
JOIN (SELECT MAX(id) AS id, product_id, MAX(DATE) AS DATE FROM test GROUP BY product_id) AS b
ON a.id = b.id AND a.product_id = b.product_id AND a.date = b.date
this time i got what i want as the result
id product_id date
------ ---------- --------
3 1 3
6 2 2
7 3 1
my problem when i add another data like below
id product_id date
------ ---------- --------
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2
6 2 2
7 3 1
8 1 3
9 1 2
and use the same query the result become like this
id product_id date
------ ---------- --------
6 2 2
7 3 1
where the the value '1' for product_id?
Try this
SELECT id, product_id, DATE FROM test sitem WHERE product_id IN (1,2,3) AND DATE = (SELECT DATE FROM test WHERE product_id =
sitem.product_id ORDER BY DATE DESC LIMIT 1) AND id =
(SELECT id FROM test WHERE product_id = sitem.product_id ORDER BY DATE DESC,
id DESC LIMIT 1) GROUP BY product_id
This is your subquery:
SELECT MAX(id) AS id, product_id, MAX(DATE) AS DATE
FROM test
GROUP BY product_id
It is independently calculating the maximum of id and date. But, there is no guarantee that these two values are in the same record. There are ways to fix the subquery, but they are rather complicated.
Instead, I would suggest using an alternative method to get the last record:
SELECT t.*
FROM test t
WHERE NOT EXISTS (SELECT 1
FROM test t2
WHERE t2.product_id = t.product_id AND
(t2.date > t.date OR
t2.date = t.date AND t2.id > t.id
);
This identifies the last record for each product as the one where no other record has a larger date. And, if two records have the same date, no other record has a larger id.

first item used by a user

I am writing a query to grab the items that a specific user_id was the first to use. Here is some sample data -
item_id used_user_id date_used
1 1 2012-08-25
1 2 2012-08-26
1 3 2012-08-27
2 2 2012-08-27
3 1 2012-08-27
4 1 2012-08-21
4 3 2012-08-24
5 3 2012-08-23
query
select item_id as inner_item_id, ( select used_user_id
from test
where test.item_id = inner_item_id
order by date_used asc
limit 1 ) as first_to_use_it
from test
where used_user_id = 1
group by item_id
It returns the correct values
inner_item_id first_to_use_it
1 1
3 1
4 1
but the query is VERY slow on a giant table. Is there a certain index that I can use or a better query that I can write?
i can't get exactly what you mean because in your inner query you have sorted it by their used_user_id and and on your outer query you have filtered it also by their userid. Why not do this directly?
SELECT DISTINCT item_id AS inner_item_id,
used_user_id AS first_to_use_it
FROM test
WHERE used_user_id = 1
UPDATE 1
SELECT b.item_id,
b.used_user_id AS first_to_use_it
FROM
(
SELECT item_ID, MIN(date_used) minDate
FROM tableName
GROUP BY item_ID
) a
INNER JOIN tableName b
ON a.item_ID = b.item_ID AND
a.minDate = b.date_used
WHERE b.used_user_id = 1