Assume the following:
CREATE TABLE #Testing
(
[id] [int] IDENTITY(1,1) NOT NULL,
[store_id] [varchar](3) NULL,
[sku] [varchar](14) NULL,
[qty] [bigint] NULL,
[http_action] [varchar](20) NULL
)
INSERT INTO #Testing (store_id, sku, qty, http_action)
SELECT '001','123456',1,'POST'
UNION ALL
SELECT '002','123456',1,'POST'
UNION ALL
SELECT '002','123456',1,'DELETE'
UNION ALL
SELECT '001','223456',5,'DELETE'
What’s a single query that you could run to return the minimum [id] for each [http_action]? Something like:
MIN_DELETE MIN_POST
3 1
GO
You can use an aggregate function with a CASE expression to get the min(id) for each http_action:
select
min(case when http_action='DELETE' then id end) Min_Delete,
min(case when http_action='POST' then id end) Min_Post
from #testing;
See SQL Fiddle with Demo.
The above query places the min(id) values into separate columns, if you want them in rows, then you could use:
select min(id) id,
http_action
from #testing
group by http_action;
See SQL Fiddle with Demo
Another way of solving it is to use a simple group by on the http_action. You will get a row for each action though:
select http_action, MIN(id) min_id from #Testing group by http_action
Output:
http_action min_id
DELETE 3
POST 1
Related
I am trying to write a query for a condition:
If >=80 percent (4 or more rows as 4/5*100=80%) of the top 5 recent rows(by Date Column), for a KEY have Value =A or =B, then change the flag from fail to pass for the entire KEY.
Here is the input and output sample:
I have highlighted recent rows with green colour in the sample.
Can someone help me in this?
I tried till finding the top 5 recent rows by the foll code:
select * from(
select *, row_number() over (partition by "KEY") as 'RN' FROM (
select * from tb1
order by date desc))
where "RN"<=5
Couldnt figure what to be done after this
Test this:
WITH
-- enumerate rows per key group
cte1 AS ( SELECT *,
ROW_NUMBER() OVER (PARTITION BY `key` ORDER BY `date` DESC) rn
FROM sourcetable ),
-- take 5 recent rows only, check there are at least 4 rows with A/B
cte2 AS ( SELECT `key`
FROM cte1
WHERE rn <= 5
GROUP BY `key`
HAVING ( SUM(`value` = 'A') >= 4
OR SUM(`value` = 'B') >= 4 )
-- AND SUM(rn = 5) )
-- update rows with found key values
UPDATE sourcetable
JOIN cte2 USING (`key`)
SET flag = 'PASS';
5.7 version – Ayn76
Convert CTEs to subqueries. Emulate ROW_NUMBER() using user-defined variable.
I have a table like this:
item_id quantity
1 2
1 3
2 NULL
2 4
3 NULL
3 NULL
And now I'm doing a SELECT like this:
SELECT
sum(`quantity`) AS `total_quantity`,
FROM `items`
GROUP BY `item_id`
Now, it return repectively 5, 4, and NULL, but I want 5, NULL and NULL.
I want that if there is a NULL value in the grouped rows, the sum should be NULL, and not the sum of the lines whose columns are not null. How can I achieve that?
Thanks!
You can use only case statement to check if any row of a group contains null as quantity
SELECT item_id,
CASE WHEN SUM(quantity IS NULL) > 0
THEN NULL
ELSE SUM(quantity)
END quantity
FROM items
GROUP BY item_id
using #Abhik Chakraborty's fiddle
DEMO
Thats kind if weird output, in most cases the request is to replace null with 0 or something else, however here is a way to do it
select
x.item_id,
max(x.quantity) as quantity from (
SELECT
t1.item_id,
#sm:= if(#prev_item = item_id, #sm_qty+quantity,quantity) as quantity,
#prev_item :=item_id,
#sm_qty:= quantity
from items t1,(select #prev_item:=null,#sm_qty=0)x
order by item_id
)x
group by x.item_id;
http://www.sqlfiddle.com/#!9/ccb36/13
SELECT * FROM (
( -- Get all not null quantities
SELECT
`i1`.`item_id`,
sum(`i1`.`quantity`) AS `total_quantity`
FROM `items` AS `i1`
WHERE `i1`.`item_id` NOT IN ( SELECT `i2`.`item_id` FROM `items` AS `i2` WHERE `i2`.`quantity` IS NULL )
GROUP BY `item_id`
)
UNION ALL
( -- Get all null quantities
SELECT
`i3`.`item_id`,
null AS `i3`.`total_quantity`
FROM `items` AS `i3`
WHERE `i3`.`item_id` IN ( SELECT `i4`.`item_id` FROM `items` AS `i4` WHERE `i4`.`quantity` IS NULL )
GROUP BY `i3.item_id`
)
) AS items_table
ORDER BY items_table.item_id
I've trying to concatenate the values of 2 GROUP_CONCAT( columns ) from a single table that's been joined twice, then get the unique items from the list.
I can do all this outside of my query but if possible it would be nice to just pull the data from the DB with a JOIN and some fancy string manipulation.
Simply put, I want to produce 1,2,3,4 from selecting 1,2,3 and 1,3,4. The 1,2,3 adn 1,3,4 are the results of the GROUP_CONCAT on the twice joined table. I can get this far:
SELECT CONCAT_WS(
",",
"1,2,3",
"1,3,4"
)
Which outputs 1,2,3,1,3,4
I'd like to be able to do something like:
-- NOTE TO SKIM READERS: THIS QUERY WILL NOT WORK
SELECT
SORT_LIST(
DISTINCT
CONCAT_WS(
",",
"1,2,3",
"1,3,4"
)
)
-- NOTE TO SKIM READERS: THIS QUERY WILL NOT WORK
But I can't find anything like that in MySQL.
The 1,2,3 and 1,3,4 have already been produced with GROUP_CONCAT( DISTINCTcol)
As stated in my comment I worked out a way to achieve distinct concatenated lists of strings using a sub query:
DROP TABLE IF EXISTS `test1234`;
CREATE TABLE `test1234` (
`val` int(1),
`type` varchar(1)
);
INSERT INTO `test1234` VALUES
( 1, 'a' ),
( 2, 'a' ),
( 3, 'a' ),
( 1, 'b' ),
( 3, 'b' ),
( 4, 'b' );
SELECT GROUP_CONCAT( `val` ) AS `vals`
FROM (
(
SELECT `val` FROM `test1234` WHERE `type` = 'a'
) UNION DISTINCT (
SELECT `val` FROM `test1234` WHERE `type` = 'b'
)
) AS `test`;
DROP TABLE IF EXISTS `test1234`;
This selected 1,2,3,4
i'm having the following database structure (for messaging):
id from_userid to_userid time_stamp message
let's say i'm user with id 1 and i want to get a list of ALL user_ids i've been interacting with, sorted by timestamp - any idea how to do it?
thanks
Something like this, perhaps?
SELECT *
FROM (
SELECT from_id AS id, time_stamp
FROM <table>
WHERE to_id=<user id>
UNION
SELECT to_id AS id, time_stamp
FROM <table>
WHERE from_id=<user id>
) AS t
ORDER BY time_stamp
SELECT *
FROM your_table
WHERE from_userid = 1 OR to_userid = 1
ORDER by time_stamp
I would do it like this:
select all values + timestamps where "me" is from_userid
select all values + timestamps where "me" is to_userid
in both selects assign the same name to the "other" user id
join the result sets using UNION ALL
then order the result by the timestamp column
group by user id and min(timestamp)
In sql it would be something like this:
select rel_user, min(time_stamp) as first_contact from
(
select time_stamp, to_userid as rel_user where from_userid=my_ID
union all
select time_stamp, from_userid as rel_user where to_userid=my_ID
)
group by rel_user
order by min(time_stamp)
Since all of the other ways use more than one SELECT here's one using CASE
SELECT CASE
WHEN to_userid=1 THEN from_userid
ELSE to_userid
FROM table WHERE to_userid=1 OR from_userid=1 ORDER BY time_stamp
I have a table like this:
Fiddle: http://sqlfiddle.com/#!2/44d9e/14
CREATE TABLE IF NOT EXISTS `mytable` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(20) NOT NULL,
`money_earned` int(20) NOT NULL,
PRIMARY KEY (`id`)
) ;
INSERT INTO mytable (user_id,money_earned) VALUES ("111","10");
INSERT INTO mytable (user_id,money_earned) VALUES ("111","6");
INSERT INTO mytable (user_id,money_earned) VALUES ("111","40");
INSERT INTO mytable (user_id,money_earned) VALUES ("222","45");
INSERT INTO mytable (user_id,money_earned) VALUES ("222","1");
INSERT INTO mytable (user_id,money_earned) VALUES ("333","5");
INSERT INTO mytable (user_id,money_earned) VALUES ("333","19");
I need to know table has how many rows, how many different users, and how many times each user has earned.
I need this result:
TOTAL_ROWS: 7
TOTAL_INDIVIDUAL_USERS: 3
USER_ID USER_TIMES
111 3
222 2
333 2
Is your problem that you want the total as well? If so, then you can get this using rollup:
SELECT coalesce(cast(user_id as char(20)), 'TOTAL USER_TIMES'),
COUNT(*) as times
FROM mytable
GROUP BY user_id with rollup;
You can get the user counts in a separate column with this trick:
SELECT coalesce(cast(user_id as char(20)), 'TOTAL USER_TIMES'),
COUNT(*) as times, count(distinct user_id) as UserCount
FROM mytable
GROUP BY user_id with rollup;
You realize that a SQL query just returns a table of values. You are asking for very specific formatting, which is typically done better at the application level. That said, you can get close to what you want with something like this:
select user, times
from ((SELECT 3 as ord, cast(user_id as char(20)) as user, COUNT(*) as times
FROM mytable
GROUP BY user_id
)
union all
(select 1, 'Total User Count', count(*)
from mytable
)
union all
(select 2, 'Total Users', count(distinct user_id)
from mytable
)
) t
order by ord;
I think this could be a typo anyway your are trying to sum your COUNT() times, simply replace with money_earned
SELECT user_id,
COUNT(*) AS 'times',
SUM(money_earned) AS 'sum_money'
FROM mytable GROUP BY user_id;
SQL Fiddle