two select queries with different where clause on same table - mysql

i have a table follower and following count..
want to get the count of both in one stored procedure.. is it possible to have two select queries with different where condition on same table possible?
CREATE TABLE Table1
([val1] int, [val2] int, [val3] int, [val4] int, other int)
;
INSERT INTO Table1
([val1], [val2], [val3], [val4], other)
VALUES
(1, 26, 13, 1, 1),
(2, 13, 26, 1, 1),
(3, 10, 26, 1, 1),
(4, 26, 13, 1, 1),
(5, 14, 26, 1, 1)
;
MY select queries
(select count(*) as following_count from table1 where val2=26)
(select count(*) as follower_count from table1 where val3=26)
SQL FIDDLE LINK

Why don't you fire both statement using UNION ALL ?
See: http://dev.mysql.com/doc/refman/5.1/de/union.html
SO:
SELECT COUNT(*) AS following_count FROM table1 WHERE val2=26
UNION ALL
SELECT COUNT(*) AS following_count FROM table1 WHERE val3=26
returns two rows with 2 numbers in 1 query.
In two columns do this:
SELECT
(SELECT COUNT(*) AS following_count FROM table1 WHERE val2=26) col1
, (SELECT COUNT(*) AS following_count FROM table1 WHERE val3=26) col2

You could do this:
SELECT
SUM(CASE WHEN val2=26 THEN 1 ELSE 0 END) AS following_count,
SUM(CASE WHEN val3=26 THEN 1 ELSE 0 END) AS follower_count
FROM
table1

Just add semicolon to your statements...
(select count(*) as following_count from table1 where val2=26);
(select count(*) as follower_count from table1 where val3=26);

Related

How to get the below result

INSERT INTO #PaymentsTable1 VALUES (1, 1, 1, 'CA')
INSERT INTO #PaymentsTable1 VALUES (2, 1, 2, 'MX')
INSERT INTO #PaymentsTable1 VALUES (1, 1, 1, 'CA')
INSERT INTO #PaymentsTable1 VALUES (2, 1, 2, 'GB')
INSERT INTO #PaymentsTable1 VALUES (1, 1, 1, 'CA')
INSERT INTO #PaymentsTable1 VALUES (2, 1, 2, 'IN')
DECLARE #Count INT
SELECT #Count = COUNT(DISTINCT PMJ.CountryCode) FROM #PaymentsTable1 PMJ GROUP BY PMJ.PId
IF (#Count >= 3)
SELECT DISTINCT Pkey, PId, DataId FROM #PaymentsTable1
ELSE
SELECT 0 AS [Pkey], 0 AS [PId], 0 AS [DataId]
I need records which are having different country code >=3
In this scenario, only the 2nd record should return. With this implementation,
what is the logic to come both PId records to come.
Since you didn't include table definition, I assumed that you have columns in following order: PKey, PId, DataId, CountryCode. So in case code doesn't work, you'll need switch order of columns :)
This should solve your problem :)
;with cte as (
select PKey, PId, DataId from #PaymentsTable1
group by PKey, PId, DataId
having Count(distinct CountryCode) >= 3
)
select * from cte
union all
select 0 as PKey, 0 as PId, 0 as DataId where not exists(select * from cte)

How to get all children of several nodes in tree structure?

I have a table with hierarchical structure like this:
Create Table tbl1
(
AccountID NVARCHAR(100),
ID int,
ParentID int
);
INSERT INTO tbl1
VALUES ('11', 1, Null), ('12', 2, Null), ('13', 3, Null),
('11/11', 4, 1), ('11/12', 5, 1), ('11/111', 6, 1),
('11/11/001', 7, 4), ('11/11/002', 8, 4), ('12/111', 9, 2),
('12/112', 10, 2);
How to get all children of some nodes from tbl1 in tree structure, according to an other table (FilteringTbl) like this:
AccountID
---------
11/11
12
13
In other words I want to create a SQL query to get all children of nodes 11/11 and 12 and 13 from my first table (tbl1) in SQL Server 2008.
Main tables have more than 5000 records. (tbl1 5400 records and filteringtbl 1500 records)
Please help me. Thanks.
;with C
as (
select AccountID,
ID,
ParentID,
0 as [level]
from tbl1
where ID IN (SELECT ID FROM Filteringtbl)
union all
select I.AccountID,
I.ID,
I.ParentID,
C.[level] + 1 as [level]
from tbl1 as I
inner join C on
C.ID = I.ParentID
)
select *
from C

get rows from a table where value of field x is maximum

I have two tables myTable and myTable2 in a mysql database:
CREATE TABLE myTable (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
number INT,
version INT,
date DATE
) ENGINE MyISAM;
INSERT INTO myTable
(`id`, `number`, `version`, `date`)
VALUES
(1, '123', '1', '2016-01-12'),
(2, '123', '2', '2016-01-13'),
(3, '124', '1', '2016-01-14'),
(4, '124', '2', '2016-01-15'),
(5, '124', '3', '2016-01-16'),
(6, '125', '1', '2016-01-17')
;
CREATE TABLE myTable2 (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
myTable_id INT
) ENGINE MyISAM;
INSERT INTO myTable2
(`id`, `myTable_id`)
VALUES
(1, 1),
(2, 1),
(3, 2),
(4, 2),
(5, 3),
(6, 3),
(7, 4),
(8, 4),
(9, 4),
(10, 5),
(11, 6)
;
The field myTable2.myTable_id is a foreign key of myTable.Id.
I would like to get all the rows from myTable where myTable2.myTable_id = myTable.Id and the value of the field version in myTable is the maximum for every corresponding value for the field number in myTable.
I tried something like this:
SELECT
*
FROM
myTable,
myTable2
WHERE
myTable.version = (SELECT MAX(myTable.version) FROM myTable)
But the above query does not return the correct data. The correct query should output this:
Id number version date
2 123 2 2016-01-13
5 124 3 2016-01-16
6 125 1 2016-01-17
Please help!
One way to do this is to get the max version for each number in myTable in a derived table and join with that:
SELECT DISTINCT
m.*
FROM
myTable m
JOIN
myTable2 m2 ON m.id = m2.myTable_id
JOIN
(
SELECT number, MAX(version) AS max_version
FROM myTable
GROUP BY number
) AS derived_table
ON m.number = derived_table.number
AND m.version = derived_table.max_version
With your sample data this produces a result like this:
id number version date
6 125 1 2016-01-17
5 124 3 2016-01-16
2 123 2 2016-01-13
your Query is logically wrong. Here is the correct one
SELECT
*
FROM
myTable,
myTable2
WHERE
(myTable.version,myTable.number) in
(SELECT MAX(myTable.version),number FROM myTable group by number)
and myTable.id=myTable2.id
Here is the sqlfiddle http://sqlfiddle.com/#!9/74a67/4/0
This is the query posted for the previous edited question
SELECT * FROM myTable
inner join myTable2 on myTable.id = myTable2.mytable_id
WHERE (version, number) in
(SELECT MAX(version), number FROM myTable group by number)
Try this solution with using subquery simply as:
# Selecting desired result..
SELECT t1.id, t1.number, t1.version, t1.date
FROM myTable As t1 JOIN
# subquery to select max version and its corresponding
# number form myTable
(SELECT number, max(version) As max_ver FROM myTable
GROUP BY number
) As t2 ON t1.number = t2.number and t1.version = t2.max_ver
# Now checking for foreign key..
WHERE t1.id IN (SELECT mytable_id FROM myTable2);
Was it helpful..

SQL query to implement multiple WHERE condition on same column

I have two tables, tbl1 and tbl2 as below:
CREATE TABLE tbl1 (`uid` int);
INSERT INTO tbl1 (`uid`)
VALUES
(100),
(200),
(300),
(400);
CREATE TABLE tbl2 (`id` int, `uid` int, `status` int);
INSERT INTO tbl2 (`id`, `uid`, `status`)
VALUES
(1, 100, 0),
(2, 100, 1),
(3, 100, 2),
(4, 100, 4),
(5, 200, 0),
(6, 200, 1),
(7, 300, 0),
(8, 300, 3),
(9, 300, 4),
(10, 400, 1),
(11, 400, 2);
SQLFIDDLE:
http://sqlfiddle.com/#!2/1a6c20/13
Problem:
I want to join these two tables.
The result should show the rows having tbl2.status = 0 but not having tbl2.status = 1.
This is the SQL query which I'm trying to run:
SELECT DISTINCT tbl1.uid, tbl2.id, tbl2.status
FROM tbl1
INNER JOIN tbl2 ON (tbl1.uid = tbl2.uid)
WHERE tbl2.status = 0
OR tbl2.status <> 1;
CORRECT expected result is: 7, 300, 0.
Here, uid=300 has a row with status=0 and this uid=0 has no row with status=1. So this is the expected result that I want.
uid=100 has both status=0 and status=1, so this is not the required result.
uid=200 also has both status=0 and status=1 so this is not the required result.
uid=400 does not have status=0, this is not the required result.
Help please!!!
You need to select uids with status=0 but not the ones that appear in your table also with status=1. So you need to exclude them from the result set. You need one more condition in your where clause to have the expected result. This can be done by using NOT IN.
Try the following query
SELECT tbl1.uid, tbl2.id, tbl2.status
FROM tbl1
INNER JOIN tbl2 ON (tbl1.uid = tbl2.uid)
WHERE tbl2.status = 0
and tbl2.uid NOT IN (SELECT uid from tbl2 where status=1);
you can use NOT EXISTS clause
SELECT DISTINCT T1.uid, T2.id, T2.status
FROM tbl1 T1
INNER JOIN tbl2 T2 ON (T1.uid = T2.uid)
WHERE T2.status = 0
AND NOT EXISTS ( SELECT 1 FROM tbl2 T22
where T2.uid = T22.uid
and T22.status =1 )
There is a logic error with the OR in the WHERE clause.
The clause WHERE tbl2.status = 0 produces the desired result:
(7, 300, 0)
The clause OR tbl2.status <> 1 produces
(7, 300, 0)
(8, 300, 3)
(9, 300, 4)
Since this is an OR the union is taken, and you get all three tuples.
People new to SQL often find OR to be tricky. I used to keep truth tables near me when an unexpected result confused me.
Remove
OR tbl2.status <> 1
It is illogical (if the column equals 0 then it can't equal 1) and confuses the query.
If you want all unique uids where status equals 0, but never equals 1, then use a subquery, with the AND logic;
WHERE tbl2.status = 0
AND tbl2.uid NOT IN (SELECT uid FROM tbl2 WHERE status=1)
This selects all the rows where status equals 0, and then removes the rows where the same uid has a status that equals 1. This will give you the expected result you gave in the question.
If you want all rows except those where status equals 1, use;
WHERE tbl2.status <> 1
Which gives you exactly the same result as the current query, the tbl2.status = 0 is irrelevant.
Putting OR doesn't make sense, just remove the OR part and Try this:
SELECT DISTINCT tbl1.uid, tbl2.id, tbl2.status
FROM tbl1
INNER JOIN tbl2 ON (tbl1.uid = tbl2.uid)
WHERE status = 0;

Get column name which has the max value in a row sql

I have a a table in my database where I store categories for newsarticles and each time a user reads an article it increments the value in the associated column. Like this:
Now I want to execute a query where I can get the column names with the 4 highest values for each record. For example for user 9, it would return this:
I've tried several things, searched a lot but don't know how to do it. Can anyone help me?
This should do it:
select
userid,
max(case when rank=1 then name end) as `highest value`,
max(case when rank=2 then name end) as `2nd highest value`,
max(case when rank=3 then name end) as `3rd highest value`,
max(case when rank=4 then name end) as `4th highest value`
from
(
select userID, #rownum := #rownum + 1 AS rank, name, amt from (
select userID, Buitenland as amt, 'Buitenland' as name from newsarticles where userID = 9 union
select userID, Economie, 'Economie' from newsarticles where userID = 9 union
select userID, Sport, 'Sport' from newsarticles where userID = 9 union
select userID, Cultuur, 'Cultuur' from newsarticles where userID = 9 union
select userID, Wetenschap, 'Wetenschap' from newsarticles where userID = 9 union
select userID, Media, 'Media' from newsarticles where userID = 9
) amounts, (SELECT #rownum := 0) r
order by amt desc
limit 4
) top4
group by userid
Demo: http://www.sqlfiddle.com/#!2/ff624/11
A very simple way of doing this is shown below
select userId, substring_index(four_highest,',',1) as 'highest value', substring_index(substring_index(four_highest,',',2),',',-1) as '2th highest value', substring_index(substring_index(four_highest,',',3),',',-1) as '3 rd highest value', substring_index(four_highest,',',-1) as '4th highest value' from
(
select userid, convert(group_concat(val) using utf8) as four_highest from
(
select userId,Buitenland as val,'Buitenland' as col from test where userid=9 union
select userId,Economie as val,' Economie' as col from test where userid=9 union
select userId,Sport as val ,'Sport' as col from test where userid=9 union
select userId,Cultuur as val,'Cultuur' as col from test where userid=9 union
select userId,Wetenschap as val,'Wetenschap' as col from test where userid=9 union
select userId,Media as val,'Media' as col from test where userid=9 order by val desc limit 4
) inner_query
)outer_query;
PL/SQL, maybe? Set user_id, query your table, store the returned row in an nx2 array of column names and values (where n is the number of columns) and sort the array based on the values.
Of course, the correct thing to do is redesign your database in the manner that #octern suggests.
This will get you started with the concept of grabbing the highest value from multiple columns on a single row (modify for your specific tables - I created a fake one).
create table fake
(
id int Primary Key,
col1 int,
col2 int,
col3 int,
col4 int
)
insert into fake values (1, 5, 9, 27, 10)
insert into fake values (2, 3, 5, 1, 20)
insert into fake values (3, 89, 9, 27, 6)
insert into fake values (4, 17, 40, 1, 20)
SELECT *,(SELECT Max(v)
FROM (VALUES (col1), (col2), (col3), (col4) ) AS value(v))
FROM fake