I have a MySQL database that contains products with their group/attributes/
i created a sample of data in
http://sqlfiddle.com/#!2/7d8a04/1
create table products (
id int(10),
title varchar(50)
);
create table attributes (
id int(10),
title varchar(50)
);
create table filters (
id int(10),
attribute_id int(10),
title varchar(50)
);
create table product_filters (
id int(10),
product_id int(10),
attribute_id int(10),
filter_id int(10)
);
#products
insert into products select '1', '1stphone';
insert into products select '2', '2ndphone';
#attributes
insert into attributes select '1', 'ram';
insert into attributes select '2', 'cpu';
insert into attributes select '3', 'hdd';
#filters
insert into filters select '1', '1','128MB';
insert into filters select '2', '1','256MB';
insert into filters select '3', '2','1GHz';
insert into filters select '4', '2','2GHz';
insert into filters select '5', '3','16GB';
insert into filters select '6', '3','32GB';
#product_filters
insert into product_filters select '1','1','1','2';
insert into product_filters select '2','1','2','4';
insert into product_filters select '3','1','3','6';
insert into product_filters select '4','2','1','1';
insert into product_filters select '5','2','2','3';
insert into product_filters select '6','2','3','5';
so I need to search that product (or products ) has 128MB OR 256MB RAM and 32GB HDD
If you see this link http://sqlfiddle.com/#!2/7d8a04/1 you can see my query
but I dont know why it return 0 row.
SELECT DISTINCT products.*
FROM products
JOIN product_filters ON product_filters.product_id=products.id
# where_ram_is_128MB_OR_256MB # it works !!
where ( product_filters.attribute_id=1 and product_filters.filter_id in (1,2) )
# and_where_hdd_is_32GB # not_works !!
AND ( product_filters.attribute_id=3 and product_filters.filter_id in (6) )
You need to join with product_filters separately for each attribute:
SELECT DISTINCT products.*
FROM products
JOIN product_filters AS f1 ON f1.product_id=products.id
JOIN product_filters AS f2 ON f2.product_id=products.id
WHERE ( f1.attribute_id=1 and f1.filter_id in (1,2) )
AND ( f2.attribute_id=3 and f2.filter_id in (6) )
DEMO
Your version tried to find a single row in product_filters that has both attribute IDs, which isn't possible.
Related
I have created: http://sqlfiddle.com/#!2/7bb44/1
CREATE TABLE if not exists tblA
(
id int(11) NOT NULL auto_increment ,
userid int(255),
category int(255),
unixtime int(255),
PRIMARY KEY (id)
);
INSERT INTO tblA (userid,category,unixtime) VALUES
('1', '1','1438689946'),
('1', '2','1438690005'),
('1', '3','1438690007'),
('5', '1','1438690009'),
('2', '1','1438690005'),
('2', '1','1438690398'),
('1', '2','1438691020'),
('1', '3','1438691028'),
('4', '2','1438690005'),
('2', '3','1438691025'),
('2', '2','1438691020'),
('3', '3','1438691022');
and
Select * from tblA group by category order by unixtime desc;
But I am getting wrong values.The values do not contain right unixtime desc.How can I make it work ? I really appreciate any help.
Try this query . If 2 unixtime are same this should display only 1
Select a.*
from tblA a join
(select category, max(unixtime) as maxut
from tblA
group by category
) c
on a.category = c.category and a.unixtime = c.maxut
group by unixtime order by a.unixtime desc;
You cannot express what you want in the way you have done it. The order by is processed after the group by. Presumably you want:
Select a.*
from tblA a join
(select category, max(unixtime) as maxut
from tblA
group by category
) c
on a.category = c.category and a.unixtime = c.maxut
order by a.unixtime desc;
I'm trying to execute this query nut it seems that it returns errors:
INSERT INTO `categories` (`name`,`path`) VALUES ('TEST 1' , 'test-1'),('TEST 2' , 'test-2'),('TEST 3' , 'test-3')
WHERE (`name`,`path`) NOT IN (SELECT `name`,`path` FROM `categories`);
Any help with this? Much appreciated.
The logic you are attempted is implemented using syntax like this:
INSERT INTO `categories` (`name`,`path`)
SELECT name, path
FROM (SELECT 'TEST 1' as name, 'test-1' as path UNION ALL
SELECT 'TEST 2', 'test-2' UNION ALL
SELECT 'TEST 3' , 'test-3'
) t
WHERE NOT EXISTS (SELECT 1
FROM categories c
WHERE c.name = t.name and c.path = t.path
);
However, you should be doing the checking in the database with a unique index. So the better solution is to do the insert and just have:
create unique index idx_categories_name_path on categories(name, path)
With an insert like:
INSERT INTO `categories` (`name`,`path`)
SELECT name, path
FROM (SELECT 'TEST 1' as name, 'test-1' as path UNION ALL
SELECT 'TEST 2', 'test-2' UNION ALL
SELECT 'TEST 3' , 'test-3'
) t
ON DUPLICATE KEY UPDATE name = VALUES(name);
I'm trying to make a query but I don't know how to do it. I'm a newbie in SQL querying, so please be patient.
Here is what I have:
select
count(*), sum(time), 'peter'
from
(select *
from ACTUATION
where OPERATOR != 'peter'
and team in (select eq1.name
from TEAMWORKS eq1
where operator1 = 'peter'
or operator2 = 'peter'
or operator3 = 'peter'
or operator4 = 'peter'
or operator5 = 'peter'
or operator6 = 'peter'
or operator7 = 'peter' )) as a
This works OK, but I need to do it for every operator in the table operators and don't know how to do it.
I've tried several subqueries and groups by, but I can not make it work properly.
Kind regards
EDIT:
Let's say I have this DataBase:
create table TEAMWORKS
(
operator1 varchar(50),
operator2 varchar(50),
operator3 varchar(50),
operator4 varchar(50),
operator5 varchar(50),
operator6 varchar(50),
operator7 varchar(50),
name varchar(50)
)
insert into TEAMWORKS (operator1,operator2,name) values ('Peter', 'Paul', 'Pe-Pa')
insert into TEAMWORKS (operator2,operator3,name) values ('Peter', 'John', 'Pe-Jo')
insert into TEAMWORKS (operator1,operator4,name) values ('John', 'Paul', 'Jo-Pa')
insert into TEAMWORKS (operator5,operator6,name) values ('John', 'Peter', 'Jo-Pe')
create table OPERATORS
(
name varchar(50),
surname varchar(50)
)
insert into OPERATORS (name,surname) values ('Peter', 'Font')
insert into OPERATORS (name,surname) values ('Paul', 'Bridges')
insert into OPERATORS (name,surname) values ('John', 'Oldfield')
create table ACTUATION
(
ID int,
time int,
operator varchar(50),
team varchar(50),
description varchar(999)
)
insert into ACTUATION (ID,time,operator,team,description) values (1,30,'Peter', '','Pick flowers')
insert into ACTUATION (ID,time,operator,team,description) values (2,15,'Paul', '','Throw flowers')
insert into ACTUATION (ID,time,operator,team,description) values (3,30,'Peter', 'Jo-Pe','Pick stones')
insert into ACTUATION (ID,time,operator,team,description) values (4,5,'John', 'Jo-Pe','Throw stones')
insert into ACTUATION (ID,time,operator,team,description) values (5,15,'Paul', 'Jo-Pa','Throw tables')
insert into ACTUATION (ID,time,operator,team,description) values (6,30,'Peter', 'Pe-Pa','Pick tables')
And I need to get the time used by Every operator in table OPERATORS where he is not the main operator in Table ACTUATIONS, but part of a TEAM in the ACTUATIONS.
In the given example, I would like to get as result:
Operator #Actuations (count) Time(sum) 'Origin (only for clarifying, list not needed)
Peter 1 5 'from actuation #4
Paul 1 30 'from actuation #6
John 2 45 'form actuations #3 and #5
Hope now it's more clear
EDIT 2:
You have a working example here: http://sqlfiddle.com/#!3/91373/6/0
That's the desired result, but obviously I would not be able to use unions as I would not know the Operators.
Edit:
After OP having altered the question, here is a working query for your example:
select top 1000
o.name
, count(1)
, sum(a.time)
from OPERATORS o
left join (
select
unpvt.Operator
, unpvt.ColName
, unpvt.name
from
(select name, operator1, operator2, operator3, operator4, operator5, operator6, operator7
from TEAMWORKS) ot
UNPIVOT (
Operator FOR ColName IN (operator1, operator2, operator3, operator4, operator5, operator6, operator7)
) as unpvt
) tw on o.name = tw.Operator
left join ACTUATION a on a.team = tw.name
where a.operator != o.name
group by o.name
This returns your decired result :)
Old Post:
I don't know the structure of the database, but I've had a go at guessing.
Firstly, i create to temporary tables in T-SQL - this is done for testing.
I've previously been down-voted for using temporary tables without descriptions in answers on SO for being to complicated, so please ask if you don't understand
declare #ACTUATION table(
time datetime default getdate()
, Operator varchar(8)
, Workteam varchar(8)
)
insert into #ACTUATION (Operator, Workteam)
select 'Gunnar', 'Peter'
union all select 'Peter', 'Gunnar'
We also need the table Teamworks:
declare #TEAMWORKS table(
time datetime default getdate()
, sometext varchar(32)
, operator1 varchar(8)
, operator2 varchar(8)
, operator3 varchar(8)
, operator4 varchar(8)
, operator5 varchar(8)
, operator6 varchar(8)
, operator7 varchar(8)
)
insert into #TEAMWORKS(sometext, operator1, operator2, operator3, operator4, operator5, operator6, operator7)
select 'Blah Blah', 'Gunnar', 'Jack', 'Sam', 'Joe', 'Lee', 'Jane', 'Jim'
union all select 'More Blah', 'Bob', 'Sal', 'Phil', 'Clark', 'Jones', 'Sue', 'Peter'
union all select 'Even more Blaah', 'Im', 'Running', 'out of', 'dummy', 'names', 'Peter', 'Gunnar'
What I've done here is to create two "virtual" tables, which only consist as variables. Eg. they are recreated each time the query is run. However, I think that they are a great tool when trying to visualize.
Next step is to UNPIVOT the operators to a more normalized structure.
This is done using the following query:
select
unpvt.time
, unpvt.sometext
, unpvt.Operator
, unpvt.ColName
from
(select time, sometext, operator1, operator2, operator3, operator4, operator5, operator6, operator7
from #TEAMWORKS) ot
UNPIVOT (
Operator FOR ColName IN (operator1, operator2, operator3, operator4, operator5, operator6, operator7)
) as unpvt;
This query should make a great starting point for further joins.
For instance, I assume that this is (partly) the result you want:
select
a.Operator
, count(1)
, max(t.time)
from #ACTUATION a
left join (
select
unpvt.Operator
, unpvt.time
from (
select time, sometext, operator1, operator2, operator3, operator4, operator5, operator6, operator7
from #TEAMWORKS
) ot
UNPIVOT (
Operator FOR ColName IN (operator1, operator2, operator3, operator4, operator5, operator6, operator7)
) as unpvt
) t on a.Workteam = t.Operator
where a.Operator != t.Operator
group by a.Operator
how to join userid to user and get the username ?
I really appreciate any help.Thanks in Advance.
http://sqlfiddle.com/#!2/ac600/1
CREATE TABLE if not exists tblA
(
id int(11) NOT NULL auto_increment ,
user varchar(255),
category int(255),
PRIMARY KEY (id)
);
CREATE TABLE if not exists tblB
(
id int(11) NOT NULL auto_increment ,
username varchar(255),
userid int(255),
PRIMARY KEY (id)
);
INSERT INTO tblA (user, category ) VALUES
('1', '1'),
('1', '2'),
('1', '3'),
('1', '1'),
('2', '1'),
('2', '1'),
('2', '1'),
('2', '1'),
('3', '1'),
('2', '1'),
('4', '1'),
('4', '1'),
('2', '1');
INSERT INTO tblB (userid, username ) VALUES
('1', 'A'),
('2', 'B'),
('3', 'C'),
('4', 'D'),
('5', 'E');
query:
SELECT
groups.*,
#rank:=#rank+1 AS rank
FROM
(select
user,
category,
count(*) as num
from
tblA
where
category=1
group by
user,
category
order by
num desc,
user) AS groups
CROSS JOIN (SELECT #rank:=0) AS init
the table looks like :
username category num Ascending rank
B 1 6 2
A 1 2 1
D 1 2 4
C 1 1 3
Use JOIN, for example:
SELECT
tblB.username,
groups.*,
#rank:=#rank+1 AS rank
FROM
(select
user,
category,
count(*) as num
from
tblA
where
category=1
group by
user,
category
order by
num desc,
user) AS groups
-- left join: in case if data integrity fails:
left join
tblB ON groups.user=tblB.userid
CROSS JOIN (SELECT #rank:=0) AS init
-check your modified demo.
You just need to do left join
SELECT
groups.*,
#rank:=#rank+1 AS rank
FROM
(select
user,
category,
count(*) as num,
tblB.username
from
tblA
left join tblB on tblA.id = tblB.userid
where
category=1
group by
user,
category
order by
num desc,
user) AS groups
CROSS JOIN (SELECT #rank:=0) AS init
See Demo
You don't need a subquery to do what you want. You can simply join in the name:
select username, category,
count(*) as num,
#rank:=#rank+1 AS rank
from tblA join
tblB
on tblA.user = tblB.userId CROSS JOIN
(SELECT #rank:=0) AS cont
where category = 1
group by username, category
order by num desc, username;
TblB has an odd format. Normally, the auto-incrementing id would be the "userid" for the table.
Also, because you are selecting only one category, strictly speaking it is unnecessary to put category in the group by statement.
EDIT:
You cannot create a view with this method of doing the rank because it uses variables. It isn't easy to generate a rank on aggregated data in a view-compatible way in MySQL.
I have two tables, first "users_counts"
id int(11) AUTO_INCREMENT
name varchar(250)
And I have second table "counts_data"
id int(11) AUTO_INCREMENT
id_user int(11)
count int(11)
date datetime
I want to select all records from the first table and get some data from a second, and then I want to merge they. I want create temp (for one request) column where collect last count with order by date in second table and second column where collect collect penultimate count with order by date in second table.
INSERT INTO `users_counts` (`id`,`name`) VALUES ('1','John');
INSERT INTO `users_counts` (`id`,`name`) VALUES ('2','Michael');
INSERT INTO `users_counts` (`id`,`name`) VALUES ('3','Den');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('1','1', '200', '2012.09.09');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('2','1', '212', '2012.09.01');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('3','2', '20', '2012.01.09');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('4','3', '210', '2012.02.09');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('5','3', '2033', '2012.03.09');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('6','3', '1', '2012.04.09');
In the end, after a request I want to get something like this
id name count count_before
1 John 200 212
2 Michael 20 0
3 Den 1 2033
Thank.
Another possible way to do this:
select uc.id,
uc.name,
(select count
from counts_data cd
where cd.id_user = uc.id
order by date desc limit 1) as count,
ifnull((select count
from counts_data cd
where cd.id_user = uc.id
order by date desc limit 1 offset 1),0) as count_before
from users_counts uc;
Since you only need one value from the counts_data for each row/record, you can use in-line queries in mySQL
SQL Fiddle
select uc.id
, uc.name
, cd1.count
, cd3.count as count_before
from users_counts uc
left join
counts_data cd1
on cd1.id_user = uc.id
and cd.date =
(
select max(date)
from counts_data cd2
where cd2.id_user = uc.id_user
)
left join
counts_data cd3
on cd3.id_user = uc.id
and cd.date =
(
select max(date)
from counts_data cd4
where cd4.id_user = uc.id_user
and cd4.date <> cd1.date
)