how can I get all usernames when I search "new1" .For eg: I should get A and B as userids 1,2 in tblC is 1,2 for row1 which has new1.What query should I use to get the above result?
I really appreciate any help.Thanks in Advance.
http://sqlfiddle.com/#!2/1ab8e/2
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)
);
CREATE TABLE if not exists tblC
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
userids varchar(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');
INSERT INTO tblC (id, nname,userids ) VALUES
('1', 'new1','1,2'),
('2', 'new2','1,3'),
('3', 'new3','1,4'),
('4', 'new4','3,2'),
('5', 'new5','5,2');
Query so far:
select * where nname="new1" from tblC
CROSS JOIN tblB
ON tblB.userid=(SELECT userids FROM substr(tblC.userids,','))
You should really look at Database normalization and first normalize your structure by adding a junction table and holds a relation from tablec each relation stored in tablec will be stored in new junction table but not as comma separated list each row will hold id of c and one user id per row ,if you can't alter your schema you can use find_in_set to find values in set
select *
from tblC c
JOIN tblB b
ON (find_in_set(b.userid,c.userids) > 0)
where c.nname="new1"
See demo
Edit for normalize schema
I have removed userids column from your tblC and instead i have created a new junction table as tblC_user with 2 columns c_id this will related to the id column of tblC and second one userid to store user relations users for tblC see sample schema for tblC
CREATE TABLE if not exists tblC
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
PRIMARY KEY (id)
);
INSERT INTO tblC (id, nname) VALUES
('1', 'new1'),
('2', 'new2'),
('3', 'new3'),
('4', 'new4'),
('5', 'new5');
And here is your junction table as tblC_user
CREATE TABLE if not exists tblC_user
(
c_id int,
userid int
);
INSERT INTO tblC_user (c_id,userid) VALUES
('1','1'),
('1','2'),
('2','1'),
('2','3'),
('3','1'),
('3','4'),
('4','3'),
('4','2'),
('5','5'),
('5','2');
In above if you notice i haven't stored any comma separated relations each relation of user for tblC is stored in new row ,for you concerned result set i have used junction table in join also new query will be like below
select *
from tblC c
join tblC_user cu on(c.id = cu.c_id)
join tblB b on (b.userid = cu.userid)
where c.nname="new1"
Demo 2
Now above query can can be optimized by using indexes you can maintain cascading relations easily
Related
how can I get all usernames when I search "new1" .For eg: I should get A and B as userids 1,2 in tblC is 1,2 for row1 which has new1.What query should I use to get the above result?
I really appreciate any help.Thanks in Advance.
http://sqlfiddle.com/#!2/1ab8e/2
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)
);
CREATE TABLE if not exists tblC
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
userids varchar(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');
INSERT INTO tblC (id, nname,userids ) VALUES
('1', 'new1','1,2'),
('2', 'new2','1,3'),
('3', 'new3','1,4'),
('4', 'new4','3,2'),
('5', 'new5','5,2');
Query so far:
select * where nname="new1" from tblC
CROSS JOIN tblB
ON tblB.userid=(SELECT userids FROM substr(tblC.userids,','))
You should really look at Database normalization and first normalize your structure by adding a junction table and holds a relation from tablec each relation stored in tablec will be stored in new junction table but not as comma separated list each row will hold id of c and one user id per row ,if you can't alter your schema you can use find_in_set to find values in set
select *
from tblC c
JOIN tblB b
ON (find_in_set(b.userid,c.userids) > 0)
where c.nname="new1"
See demo
Edit for normalize schema
I have removed userids column from your tblC and instead i have created a new junction table as tblC_user with 2 columns c_id this will related to the id column of tblC and second one userid to store user relations users for tblC see sample schema for tblC
CREATE TABLE if not exists tblC
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
PRIMARY KEY (id)
);
INSERT INTO tblC (id, nname) VALUES
('1', 'new1'),
('2', 'new2'),
('3', 'new3'),
('4', 'new4'),
('5', 'new5');
And here is your junction table as tblC_user
CREATE TABLE if not exists tblC_user
(
c_id int,
userid int
);
INSERT INTO tblC_user (c_id,userid) VALUES
('1','1'),
('1','2'),
('2','1'),
('2','3'),
('3','1'),
('3','4'),
('4','3'),
('4','2'),
('5','5'),
('5','2');
In above if you notice i haven't stored any comma separated relations each relation of user for tblC is stored in new row ,for you concerned result set i have used junction table in join also new query will be like below
select *
from tblC c
join tblC_user cu on(c.id = cu.c_id)
join tblB b on (b.userid = cu.userid)
where c.nname="new1"
Demo 2
Now above query can can be optimized by using indexes you can maintain cascading relations easily
I want to get count of post subscribed by user below is my table schema , please help me with query for the same, i trie many option but could not do it
I tried and was able to get post count of user below is my query , but here i have used static user id , i want single query to list count for all users
SELECT COUNT(*)
FROM CATMAPPING INNER JOIN
POST ON CATMAPPING.pid = POST.id
where FIND_IN_SET(CATMAPPING.cid,(select selectedcatid from subscribers where id='1'));
Desire OP
Desired Output
uemail Postcount
-----------------------------
a#s.com 4
b#s.com 8
c#s.com 10
d#s.com 4
SQL fiddel link : http://sqlfiddle.com/#!9/4fff8f/2
CREATE TABLE subscribers (
`id` int(10),
`uemail` varchar(255) DEFAULT NULL,
`selectedcatid` varchar(255) DEFAULT NULL
) ;
ALTER TABLE subscribers ADD PRIMARY KEY (`id`);
ALTER TABLE subscribers MODIFY `id` int(10) unsigned NOT NULL AUTO_INCREMENT;
INSERT INTO subscribers (`uemail`, `selectedcatid`) VALUES ('a#s.com', '1'),
('b#s.com', '1,3'),
('c#s.com', '1,2,3'),
('d#s.com', '3');
CREATE TABLE POST (
`id` int(10),
`title` varchar(255) DEFAULT NULL
) ;
INSERT INTO POST (`id`, `title`) VALUES ('1', 'ABC'),
('2', 'DEF'),
('3', 'GHI'),
('4', 'JKL'),
('5', 'MNO'),
('6', 'PQR'),
('7', 'STU'),
('8', 'VXZ'),
('9', 'ASO'),
('10', 'LMO');
CREATE TABLE CATMAPPING (
`cid` int(10),
`pid` int(10) DEFAULT NULL
) ;
INSERT INTO CATMAPPING (`pid`, `cid`) VALUES ('1', '1'),
('2', '2'),
('3', '3'),
('4', '1'),
('5', '2'),
('6', '3'),
('7', '3'),
('8', '3'),
('9', '1'),
('10', '1');
Here is the correct query I wrote in sql server may be some syntax is diffrent but it gives me correct result I creates a table valued function and then used it for the query .
declare #tempsub as table (subid int,selectcatId int )
insert into #tempsub
select id ,string
from subscribers
CROSS APPLY [dbo].[ufn_CSVToTable] (selectedcatid)
--select * from #tempsub
-- subid is the id of the subscribes table
SELECT subid , count(*) from post p inner join CATMAPPING c on c.pid = p.id
left join #tempsub t on t.selectcatId= c.cid
group by t.subid
-- below is the code for tabled valued function it return a table for comma seprated string
create FUNCTION dbo.[ufn_CSVToTable] ( #StringInput VARCHAR(8000) )
RETURNS #OutputTable TABLE ( [String] nVARCHAR(1000) )
AS
BEGIN
DECLARE #String nVARCHAR(1000)
WHILE LEN(#StringInput) > 0
BEGIN
SET #String = LEFT(#StringInput,
ISNULL(NULLIF(CHARINDEX(',', #StringInput) - 1, -1),
LEN(#StringInput)))
SET #StringInput = SUBSTRING(#StringInput,
ISNULL(NULLIF(CHARINDEX(',', #StringInput), 0),
LEN(#StringInput)) + 1, LEN(#StringInput))
INSERT INTO #OutputTable ( [String] )
VALUES ( #String )
END
RETURN
END
how can I get all usernames when I search "new1" .For eg: I should get A and B as userids 1,2 in tblC is 1,2 for row1 which has new1.What query should I use to get the above result?
I really appreciate any help.Thanks in Advance.
http://sqlfiddle.com/#!2/1ab8e/2
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)
);
CREATE TABLE if not exists tblC
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
userids varchar(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');
INSERT INTO tblC (id, nname,userids ) VALUES
('1', 'new1','1,2'),
('2', 'new2','1,3'),
('3', 'new3','1,4'),
('4', 'new4','3,2'),
('5', 'new5','5,2');
Query so far:
select * where nname="new1" from tblC
CROSS JOIN tblB
ON tblB.userid=(SELECT userids FROM substr(tblC.userids,','))
You should really look at Database normalization and first normalize your structure by adding a junction table and holds a relation from tablec each relation stored in tablec will be stored in new junction table but not as comma separated list each row will hold id of c and one user id per row ,if you can't alter your schema you can use find_in_set to find values in set
select *
from tblC c
JOIN tblB b
ON (find_in_set(b.userid,c.userids) > 0)
where c.nname="new1"
See demo
Edit for normalize schema
I have removed userids column from your tblC and instead i have created a new junction table as tblC_user with 2 columns c_id this will related to the id column of tblC and second one userid to store user relations users for tblC see sample schema for tblC
CREATE TABLE if not exists tblC
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
PRIMARY KEY (id)
);
INSERT INTO tblC (id, nname) VALUES
('1', 'new1'),
('2', 'new2'),
('3', 'new3'),
('4', 'new4'),
('5', 'new5');
And here is your junction table as tblC_user
CREATE TABLE if not exists tblC_user
(
c_id int,
userid int
);
INSERT INTO tblC_user (c_id,userid) VALUES
('1','1'),
('1','2'),
('2','1'),
('2','3'),
('3','1'),
('3','4'),
('4','3'),
('4','2'),
('5','5'),
('5','2');
In above if you notice i haven't stored any comma separated relations each relation of user for tblC is stored in new row ,for you concerned result set i have used junction table in join also new query will be like below
select *
from tblC c
join tblC_user cu on(c.id = cu.c_id)
join tblB b on (b.userid = cu.userid)
where c.nname="new1"
Demo 2
Now above query can can be optimized by using indexes you can maintain cascading relations easily
How to get the tablenames where nname is "new5" in all tables?.I have tried the query below but I dont get the solution(I dont think the query is right either).I really appreciate any help.Thanks in Advance.
http://sqlfiddle.com/#!2/aa1b8/7
CREATE TABLE if not exists tblC1
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
PRIMARY KEY (id)
);
INSERT INTO tblC1 (id, nname) VALUES
('1', 'new1'),
('2', 'new2'),
('3', 'new3'),
('4', 'new4'),
('5', 'new5');
CREATE TABLE if not exists tblC2
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
PRIMARY KEY (id)
);
INSERT INTO tblC2 (id, nname) VALUES
('1', 'new1'),
('2', 'new21'),
('3', 'new31'),
('4', 'new41'),
('5', 'new51');
CREATE TABLE if not exists tblC3
(
id int(11) NOT NULL auto_increment ,
nname varchar(255),
PRIMARY KEY (id)
);
INSERT INTO tblC3 (id, nname) VALUES
('1', 'new1'),
('2', 'new21'),
('3', 'new31'),
('4', 'new41'),
('5', 'new5');
Query:
SELECT *
FROM (SELECT * FROM tblC1
UNION SELECT * FROM tblC2
UNION SELECT * FROM tblC3 ) as t2
where nname = "new5"
Add the table name to your single selects:
SELECT * FROM (
SELECT
'tblC1' as tbl, tblC1.*
FROM tblC1
UNION SELECT 'tblC2', tblC2.* FROM tblC2
UNION SELECT 'tblC3', tblC3.* FROM tblC3
) t
where t.nname = "new5"
should do. You need either the outer select or a where clause for every single select of your unions. And you've got to specify the tablename,
Fiddle
I am using the code below to retrieve the latest data w.r.t all users .But if the user had points added at the same time stamp then I would like to get the last entry not both like in the example below.How do I make sure that I get latest entry even if 2 records have same timestamp.
http://sqlfiddle.com/#!2/374db/1
I really appreciate any help.Thanks in Advance.
CREATE TABLE if not exists tblA
(
id int(11) NOT NULL auto_increment ,
sender varchar(255),
receiver varchar(255),
msg varchar(255),
date timestamp,
points varchar(255),
refno varchar(255),
PRIMARY KEY (id)
);
CREATE TABLE if not exists tblB
(
id int(11) NOT NULL auto_increment ,
sno varchar(255),
name varchar(255),
PRIMARY KEY (id)
);
CREATE TABLE if not exists tblC
(
id int(11) NOT NULL auto_increment ,
data varchar(255),
refno varchar(255),
extrarefno varchar(255),
PRIMARY KEY (id)
);
INSERT INTO tblA (sender, receiver,msg,date,points,refno ) VALUES
('1', '2', 'buzz ...','2011-08-21 14:11:09','10','001'),
('1', '2', 'test ...','2011-08-21 14:12:19','20','002'),
('4', '2', 'test ...','2011-08-21 14:13:19','30','003'),
('1', '3', 'buzz ...','2011-08-21 14:11:09','10','004'),
('1', '3', 'test ...','2011-08-21 14:12:19','20','005'),
('1', '4', 'buzz ...','2011-08-21 14:11:09','10','006'),
('1', '4', 'test ...','2011-08-21 14:12:19','20','007'),
('3', '4', 'test ...','2011-08-21 14:13:19','20','008'),
('2', '4', 'test ...','2011-08-21 14:13:19','20','009');
INSERT INTO tblB (sno, name ) VALUES
('1', 'Aa'),
('2', 'Bb'),
('3', 'Cc'),
('4', 'Dd'),
('5', 'Ee'),
('6', 'Ff'),
('7', 'Gg'),
('8', 'Hh');
INSERT INTO tblC (data,refno,extrarefno ) VALUES
('data1', '001', '101'),
('data2', '002', '102'),
('data3', '003', '103'),
('data4', '004', '101'),
('data5', '005', '102'),
('data6', '006', '103'),
('data7', '007', '101'),
('data8', '008', '101'),
('data9', '009', '101');
///
query:
SELECT *
FROM (
SELECT tblB.*, MAX(tblA.date) AS date
FROM tblB
JOIN tblA ON tblB.sno = tblA.receiver
GROUP BY tblB.sno
) AS subset
JOIN tblA ON subset.sno = tblA.receiver
AND subset.date = tblA.date JOIN tblC ON tblA.refno=tblC.refno
The key idea is to use the id column instead of the date column. It is auto-incremented, so the biggest id should be more recent.
However, your query has another problem which is the join to tblB in the subquery. Arbitrary ("indeterminate") values from tblB would be returned in the outer query. Instead, just aggregate on tblA and move the join to tblB to the outer level:
SELECT *
FROM (SELECT tblA.receiver, MAX(tblA.id) AS id
FROM tblA
GROUP BY tblA.receiver
) subset JOIN
tblA
ON subset.receiver = tblA.receiver AND subset.id = tblA.id JOIN
tblB
on tblA.receiver = tblB.sno join
tblC
ON tblA.refno=tblC.refno ;
Order by the date AND the id. The id is set to auto increment, if the date is the same, you can assume the higher id was created after.
ORDER BY date, id