How to select rows where a combination of 2 columns is the same - sql

The title seems to do a really poor job at describing my problem; let me try and explain it with a simplified example:
lets say I have the following table:
_______________________
|id|variant_id|attr_id|
|__|__________|_______|
|1 |15 |110 |
|2 |15 |110 |
|3 |20 |152 |
|4 |20 |110 |
|5 |21 |110 |
|__|__________|_______|
Now, what I'd like to have is a query that selects all rows where a combination of the variant_id and attr_id columns occurs more than once. Basically in this example it should select row 1 and 2, because their combination of variant_id and attr_id occurs more than once in the table.
Is that possible? My head hurts from trying to think of a possible solution.

SELECT variant_id, attr_id
FROM YouTable
GROUP BY variant_id, attr_id
HAVING COUNT(*) > 1

Try this query
SELECT a.* FROM
tbl a
inner join
tbl b
ON a.variant_id =b.variant_id AND a.attr_id = b.attr_id
WHERE a.id <> b.id;
Hope this helps

Related

select categories where their parent is type 1

I have this table categories
|catId |catName|catParentID|catType|
-------------------------------------
|1 |cat1 |null |6 |
|2 |cat2 |null |9 |
|3 |cat3 |1 |6 |
|4 |cat4 |2 |9 |
|5 |cat5 |1 |6 |
|6 |cat6 |3 |8 |
the parents are in the same table with the sub categories only they have no parent.
i need to get all the sub categories that their parent's type is 6.
the output of the example above should look like this-
cat3
cat5
Given your data structure, this seems to work:
select c.*
from categories c
where c.catParentID is not null and -- has a parent
c.catType = 6;
However, that might not be a general solution. So you can use a self-join:
select c.*
from categories c join
categories cp
on c.catParentID = cp.catID
where cp.catType = 6;
SELECT *
FROM categories
WHERE cattype = 6
AND catparentid IS NOT NULL
The Simplest way is,
SELECT * FORM categories WHERE catParentId ='1' AND catType ='6'
Try this... (Based on your desired output)
SELECT t1.*
FROM tablename t1
LEFT JOIN tablename t2 ON t1.catparentid = t2.catid
WHERE t2.cattype = 6
AND t2.catparentid IS NULL

How can I count occasions of grouped values in a table?

I have the table in my postgres db below. I would like to know how many times the the values (name1, name2, name3) occur in the table where trial is 1.
In the case below the expected output:
name1, 4
name2, 3
name3, 2
+--------------+
| id|name|trial|
+--------------+
|1 |name1|1 |
|2 |name1|1 |
|3 |name1|1 |
|4 |name1|1 |
|5 |name2|1 |
|6 |name2|1 |
|7 |name2|1 |
|8 |name3|1 |
|9 |name3|1 |
What I tried so far:
SELECT count(C.NAME)
FROM FIRST AS C
WHERE NAME = (
SELECT CS.NAME
FROM FIRST AS CS
WHERE TRIAL = 1
GROUP BY CS.NAME
)
this query returns with 9, which is number of rows.
You're missing the group by clause. Also, the query can be simplified, try this:
SELECT count(1), Name
FROM FIRST
WHERE TRIAL = 1
GROUP BY Name

SQL Server recursive query with associated table

I have a typical parent/child relationship table to represent folders. My challenge is using it in conjunction with another table.
The folder table is like this:
+--+----+--------+
|id|name|parentid|
+--+----+--------+
|1 |a |null |
+--+----+--------+
|2 |b |1 |
+--+----+--------+
|3 |c1 |2 |
+--+----+--------+
|4 |c2 |2 |
+--+----+--------+
The association table is like this:
+--+--------+
|id|folderid|
+--+--------+
|66|2 |
+--+--------+
|77|3 |
+--+--------+
so that where association.id = 66 has a relationship to folder.id = 2
What I need to do is find the association.id of the first ancestor with a record in the association table.. Using the example data above, given folder.id of 3 I expect to find 77; given folder.id of 2 or 4 I expect to find 66; any other folder.id value would find null.
Finding folder ancestry can be done with a common table expression like this:
WITH [recurse] (id,name,parentid,lvl) AS
(
select a.id,a.name,a.parentid,0 FROM folder AS a
WHERE a.id='4'
UNION ALL
select r.id,r.name,r.parentid,lvl+1 FROM folder as r
INNER JOIN [recurse] ON recurse.parentid = r.id
)
SELECT * from [recurse] ORDER BY lvl DESC
yielding the results:
+--+----+--------+---+
|id|name|parentid|lvl|
+--+----+--------+---+
|1 |a | |2 |
+--+----+--------+---+
|2 |b |1 |1 |
+--+----+--------+---+
|4 |c2 |2 |0 |
+--+----+--------+---+
To include the association.id I've tried using a LEFT JOIN in the recursive portion of the CTE, but this is not allowed by SQL Server.
What workaround do I have for this?
Or better yet, is the a way to query directly for the particular association.id? (e.g., without walking through the results of the CTE query that I have been attempting)
SELECT r.id, r.name, r.parentid, r.lvl, a.folderid, a.id as associationid
FROM [recurse] r
LEFT JOIN [association] a
ON r.id = a.folderid
WHERE a.folderId IS NOT NULL
ORDER BY lvl DESC
This will give you the records that have values in the association table. Then you could limit it to the first record that has a value or just grab the top result

count and distinct over multiple columns

I have a database table containing two costs. I want to find the distinct costs over these two columns. I also want to find the count that these costs appear. The table may look like
|id|cost1|cost2|
|1 |50 |60 |
|2 |20 |50 |
|3 |50 |70 |
|4 |20 |30 |
|5 |50 |60 |
In this case I want a result that is distinct over both columns and count the number of times that appears. So the result I would like is
|distinctCost|count|
|20 |2 |
|30 |1 |
|50 |4 |
|60 |2 |
|70 |1 |
and ideally ordered
|disctinCost1|count|
|50 |4 |
|60 |2 |
|20 |2 |
|70 |1 |
|30 |1 |
I can get the distinct over two columns by doing something like
select DISTINCT c FROM (SELECT cost1 AS c FROM my_costs UNION SELECT cost2 AS c FROM my_costs);
and I can get the count for each column by doing
select cost1, count(*)
from my_costs
group by cost1
order by count(*) desc;
My problem is how can I get the count for both columns? I am stuck on how to do the count over each individual column and then add it up.
Any pointers would be appreciated.
I am using Oracle DB.
Thanks
By combining your two queries..
select cost, count(*)
from
(
SELECT id, cost1 AS cost FROM my_costs
UNION ALL
SELECT id, cost2 AS c FROM my_costs
) v
group by cost
order by count(*) desc;
(If when a row has cost1 and cost2 equal, you want to count it once not twice, change the union all to a union)
You can use the unpivot statement :
select *
from
(
SELECT cost , count(*) as num_of_costs
FROM my_costs
UNPIVOT
(
cost
FOR cost_num IN (cost1,cost2)
)
group by cost
)
order by num_of_costs desc;

SQL Group by one column, count entries in another

I'm using a sqlite3 database, with a table like this.
|name |action |
-------------------------
|john |run |
|jim |run |
|john |run |
|john |jump |
|jim |jump |
|jim |jump |
|jim |dive |
I want to get an output like this
|name |run |jump |dive |
---------------------------------
|john |2 |1 |0 |
|jim |1 |2 |1 |
The closest I've come is with this, but I would like to have a single row like above.
SELECT name, action, COUNT(name)
FROM table
GROUP BY name, action
|name |action |COUNT(name) |
|john |run |2 |
|john |jump |1 |
|jim |run |1 |
|jim |jump |2 |
|jim |dive |1 |
Also, I will need to have some WHERE statements in the query as well.
Am I up in the night thinking this will work?
You can also accomplish what you want by using a sum aggregate and CASE conditions like this:
SELECT name,
sum(CASE WHEN action = 'run' THEN 1 END) as run,
sum(CASE WHEN action = 'jump' THEN 1 END) as jump,
sum(CASE WHEN action = 'dive' THEN 1 END) as dive
FROM table
GROUP BY name
You will still have to change the query every time additional actions are added.
What you are trying to do is called cross tabulation. Normally this is available as a feature called pivot table in Excel and other spreadsheet softwares.
I have found a blog article which will help you with this using SQL. Check out pivot-table-hack-in-sqlite3-and-mysql
I don't know SQLLite that well, but I image that you could use subqueries or temp tables.
With mssql you could write something like this:
select Name,
(select count(*) from table as t1 where t1.Name = table.Name and t1.Action = 'run') as Run,
(select count(*) from table as t1 where t1.Name = table.Name and t1.Action = 'dive') as dive,
(select count(*) from table as t1 where t1.Name = table.Name and t1.Action = 'jump') as run
from table
But this would need to be rewritten every time you ad another action type. You should probably add an index to get the speed up on the table. But check the query plan with "real" data first.
in oracle database you can write like below query to show required solution :-
select * from table_name
pivot (count(*) for action in ('run','jump','drive'))
this will give the desired output..