Getting wrong data from relation - sql

I have 2 tables:
DesignGroup table:
+--------------------------------------+--------+
| DesignGroupId | Name |
+--------------------------------------+--------+
| 9D32C543-24EA-497E-918E-387C8A66BF1A | Group1 |
| 532C543E-24EA-497E-918E-387C8A66BF1A | Group2 |
+--------------------------------------+--------+
Design table:
+-----------+---------------+--------------------------------------+
| DesignKey | Name | DesignGroupId |
+-----------+---------------+--------------------------------------+
| 1 | Design | 9D32C543-24EA-497E-918E-387C8A66BF1A |
| 2 | Design | 9D32C543-24EA-497E-918E-387C8A66BF1A |
| 3 | AnotherDesign | 532C543E-24EA-497E-918E-387C8A66BF1A |
+-----------+---------------+--------------------------------------+
As you can see multiple designs can have same DesignGroupId, So I make a query like:
DECLARE #DesignName VARCHAR(255) = 'Design'
SELECT
[D].[Name] AS [Display],
[D].[DesignKey] AS [Value]
FROM
[Design] AS [D]
JOIN
[DesignGroup] AS [DG] ON [D].[DesignGroupId] = [DG].[DesignGroupId]
GROUP BY
[D].[Name], [D].[DesignKey];
My desire result of this, is get only one value one [Display] and one [Value] of each DesignGroupId, so my desire result there was:
+---------------+-------+
| Display | Value |
+---------------+-------+
| Design | 1 |
| AnotherDesign | 3 |
+---------------+-------+
But I'm getting result foreach DesignKey like:
+---------------+-------+
| Display | Value |
+---------------+-------+
| Design | 1 |
| Design | 2 |
| AnotherDesign | 3 |
+---------------+-------+
How can I solve this? Regards

I don't see why you need to join the tables.
The results you want depend only on the data from the table [Design].
So GROUP BY [Name] and get the minimum value of [DesignKey]:
SELECT
[Name] AS [Display],
MIN([DesignKey]) AS [Value]
FROM [Design]
GROUP BY [Name];
But this will be fine if the table has only one value for DesignGroupId.
What do you need as a result for the other DesignGroupIds?
Maybe GROUP BY [DesignGroupId], [Name]:
SELECT
[DesignGroupId],
[Name] AS [Display],
MIN([DesignKey]) AS [Value]
FROM [Design]
GROUP BY [DesignGroupId], [Name];

Is your objective to get the minimum DesignKey value for each Name (Display) and Group? You can wrap your result into a minimum value outer query:
SELECT DISPLAY, MIN(VALUE) from (
SELECT
[D].[Name] AS [Display],
[D].[DesignKey] AS [Value]
FROM
[Design] AS [D]
JOIN
[DesignGroup] AS [DG] ON [D].[DesignGroupId] = [DG].[DesignGroupId]
GROUP BY
[D].[Name], [D].[DesignKey])
GROUP BY Display;

Related

Multiple queries resulting in minimum number of occurrences

I need to find the smallest number of documents retrieved by any subject based on exp_condition. Exp_condition from the subjects table contains a '1' and a '2' column.
Here are the tables:
subjects table:
+-----------------+--------------+
| Field | Type |
+-----------------+--------------+
| username | varchar(255) |
| user_type | varchar(10) |
| years | int |
| low_grade | int |
| high_grade | int |
| on_line | varchar(10) |
| on_line_sources | varchar(255) |
| location | varchar(5) |
| exp_condition | int |
+-----------------+--------------+
tasks table:
+------------+--------------+
| Field | Type |
+------------+--------------+
| username | varchar(255) |
| task | varchar(5) |
| confidence | int |
| sim_helpd | int |
+------------+--------------+
docs table:
+--------------+--------------+
| Field | Type |
+--------------+--------------+
| username | varchar(255) |
| task | varchar(5) |
| doc_type | varchar(10) |
| used_tool | int |
| relevant | int |
| motivational | int |
| concepts | int |
| background | int |
| grade_level | int |
| hands_on | int |
| attachments | int |
+--------------+--------------+
I'm able to generate the number of subjects and number of documents for both exp_condition values. I'm allowed to use multiple queries, but I'm not sure how.
Code for generating number of subjects for exp_condition 1 and 2:
select count(distinct(t2.username))
from tasks as t1
inner join subjects as t2
on t1.username = t2.username group by exp_condition;
Code for generating number of documents for exp_condition 1 and 2:
select count(*), exp_condition
from docs as t1
left join subjects as t2
on t1.username = t2.username
group by exp_condition;
Expected output: two separate numbers for smallest number of documents retrieved by any subject based on exp_condition.
Thanks in advance.
You can use a subquery or a CTE
SubQuery
SELECT exp_condition, MIN(A) as Tasks, MIN(B) as Docs FROM (
SELECT exp_condition, COUNT(DISTINCT t2.username) A, COUNT(DISTINCT (t3.username) B
FROM subjects s
LEFT JOIN tasks T2 ON s.username = t2.username
LEFT JOIN docs T3 ON s.username = t3.username
GROUP BY exp_condition
) A
GROUP BY ex_condition
CTE
;WITH CTE AS (
SELECT exp_condition, COUNT(DISTINCT t2.username) A, COUNT(DISTINCT (t3.username) B
FROM subjects s
LEFT JOIN tasks T2 ON s.username = t2.username
LEFT JOIN docs T3 ON s.username = t3.username
GROUP BY exp_condition
)
SELECT exp_condition, MIN(A) as Tasks, MIN(B) as Docs
FROM CTE
GROUP BY ex_condition

Get higest value of each relation

I have Project table, ProjectDesign Table and Design Table
So each project have multiple Designs and they are related by ProjectDesign table
Like this
Project Table
+------------+----------+
| ProjectKey | Name |
+------------+----------+
| 1 | Project1 |
| 2 | Project2 |
| 3 | Project3 |
+------------+----------+
ProjectDesign Table
+------------+-----------+
| ProjectKey | DesignKey |
+------------+-----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 1 | 4 |
| 1 | 5 |
+------------+-----------+
Design Table
+-----------+------+
| DesignKey | Name |
+-----------+------+
| 1 | Key1 |
| 2 | Key2 |
| 3 | Key3 |
| 4 | Key4 |
| 5 | Key5 |
+-----------+------+
That I want to do is to select MAX designKey of each project. I try as:
SELECT MAX([PD].[DesignKey])
FROM [Project] AS [p]
INNER JOIN [ProjectDesign] AS [PD] ON [PD].[ProjectKey] = [P].[ProjectKey]
INNER JOIN [Design] AS [D] ON [PD].[DesignKey] = [D].[DesignKey]
But it only gets one value, and its the highest design key, but I want highest design key of each project. How can I achieve that?
You can simply do this:
SELECT [p].ProjectKey, max([PD].[DesignKey])
FROM [Project] AS [p]
INNER JOIN [ProjectDesign] AS [PD] ON [PD].[ProjectKey] = [P].[ProjectKey]
INNER JOIN [Design] AS [D] ON [PD].[DesignKey] = [D].[DesignKey]
group by [p].ProjectKey;
Only bridge table is enough for you to get this
SELECT ProjectKey, max(DesignKey)
From ProjectDesign
Group by ProjectKey
You can use GROUP BY or a Windowing function to do this -- here is how to do it with a windowing function:
SELECT MAX([PD].[DesignKey]) OVER (PARTITION BY PD.ProjectKey) AS MAX_BY_PROJECT
FROM [Project] AS [p]
INNER JOIN [ProjectDesign] AS [PD] ON [PD].[ProjectKey] = [P].[ProjectKey]
INNER JOIN [Design] AS [D] ON [PD].[DesignKey] = [D].[DesignKey]

SQL select multiple values present in multiple columns

I have two tables DiagnosisCodes and DiagnosisConditions as shown below. I need to find the members(IDs) who have a combination of Hypertension and Diabetes. The problem here is the DiagnosisCodes are spread across 10 columns. How do I check if the member qualifies for both conditions
DiagnosisCodes
+----+-------+-------+-------+-----+--------+
| ID | Diag1 | Diag2 | Diag3 | ... | Diag10 |
+----+-------+-------+-------+-----+--------+
| A | 2502 | 2593 | NULL | ... | NULL |
| B | 2F93 | 2509 | 2593 | ... | NULL |
| C | C257 | 2509 | C6375 | ... | NULL |
+----+-------+-------+-------+-----+--------+
DiagnosisConditions
+------+--------------+
| Code | Condition |
+------+--------------+
| 2502 | Hypertension |
| 2593 | Diabetes |
| 2509 | Diabetes |
| 2F93 | Hypertension |
| 2673 | HeartFailure |
+------+--------------+
Expected Result
+---------+
| Members |
+---------+
| A |
| B |
+---------+
How do I query to check Mulitple values which are present in Multiple columns. Do you suggest to use EXISTS?
SELECT DISTINCT id
FROM diagnosiscodes
WHERE ( diag1, diag2...diag10 ) IN (SELECT code
FROM diagnosiscondition
WHERE condition IN ( 'Hypertension','Diabetes' )
)
I would do this using group by and having:
select dc.id
from diagnosiscodes dc join
diagnosiscondistions dcon
on dcon.code in (dc.diag1, dc.diag2, . . . )
group by id
having sum(case when dcon.condition = 'diabetes' then 1 else 0 end) > 0 and
sum(case when dcon.condition = 'Hypertension' then 1 else 0 end) > 0;
Then, you should fix your data structure. Having separate columns with the same information distinguished by a number is usually a sign of a poor data structure. You should have a table, called somethhing like PatientDiagnoses with one row per patient and diagnosis.
Here is one way by unpivoting the data
SELECT DISTINCT id
FROM yourtable
CROSS apply (VALUES (Diag1),(Diag2),..(Diag10))tc(Diag)
WHERE Diag IN (SELECT code
FROM diagnosiscondition
WHERE condition IN ( 'Hypertension', 'Diabetes' ) group by code having count(distinct condition)=2)

how to bake in a record count in a sql query

I have a query that looks like this:
select id, extension, count(distinct(id)) from publicids group by id,extension;
This is what the results looks like:
id | extension | count
-------------+-------------------------+-------
18459154909 | 12333 | 1
18459154909 | 9891114 | 1
18459154919 | 43244 | 1
18459154919 | 8776232 | 1
18766145025 | 12311 | 1
18766145025 | 1122111 | 1
18766145201 | 12422 | 1
18766145201 | 14141 | 1
But what I really want is for the results to look like this:
id | extension | count
-------------+-------------------------+-------
18459154909 | 12333 | 2
18459154909 | 9891114 | 2
18459154919 | 43244 | 2
18459154919 | 8776232 | 2
18766145025 | 12311 | 2
18766145025 | 1122111 | 2
18766145201 | 12422 | 2
18766145201 | 14141 | 2
I'm trying to get the count field to show the total number of records that have the same id.
Any suggestions would be appreciated
I think you want to count distincts extentions, not ids.
Run this query:
select id
, extension
(select count(*) from publicids p1 where p.id = p1.id ) distinct_id_count
from publicids p
group by id,extension;
This is more or less the same as Pastor's answer. Depending on what the optimizer does it might be faster with higher record count source tables.
select p.id, p.extension, p2.id_count
from publicids p
inner join (
select id, count(*) as id_count
from publicids group by id
) as p2 on p.id = p2.id

How to apply a SUM operation without grouping the results in SQL?

I have a table like this one:
+----+---------+----------+
| id | group | value |
+----+---------+----------+
| 1 | GROUP A | 0.641028 |
| 2 | GROUP B | 0.946927 |
| 3 | GROUP A | 0.811552 |
| 4 | GROUP C | 0.216978 |
| 5 | GROUP A | 0.650232 |
+----+---------+----------+
If I perform the following query:
SELECT `id`, SUM(`value`) AS `sum` FROM `test` GROUP BY `group`;
I, obviously, get:
+----+-------------------+
| id | sum |
+----+-------------------+
| 1 | 2.10281205177307 |
| 2 | 0.946927309036255 |
| 4 | 0.216977506875992 |
+----+-------------------+
But I need a table like this one:
+----+-------------------+
| id | sum |
+----+-------------------+
| 1 | 2.10281205177307 |
| 2 | 0.946927309036255 |
| 3 | 2.10281205177307 |
| 4 | 0.216977506875992 |
| 5 | 2.10281205177307 |
+----+-------------------+
Where summed rows are explicitly repeated.
Is there a way to obtain this result without using multiple (nested) queries?
IT would depend on your SQL server, in Postgres/Oracle I'd use Window Functions. In MySQL... not possible afaik.
Perhaps you can fake it like this:
SELECT a.id, SUM(b.value) AS `sum`
FROM test AS a
JOIN test AS b ON a.`group` = b.`group`
GROUP BY a.id, b.`group`;
No there isn't AFAIK. You will have to use a join like
SELECT t.`id`, tsum.sum AS `sum`
FROM `test` as t GROUP BY `group`
JOIN (SELECT `id`, SUM(`value`) AS `sum` FROM `test` GROUP BY `group`) AS tsum
ON tsum.id = t.id