Multiplying fields from separate columns which have the same ID in SQL? - sql

I have two tables which are joined by an ID...
table 1
- Assessment ID
- Module ID
- Assessment Weighting
table 2
- ID
- AssessmentID
- ModuleID
- UserID
- MarkFrom100
An assessment can have many students taking the assessment.
For example
A module has two assessments, one worth 60% and the other worth 40%. in table 2, I want to take the weighting value from table 1 and multiply it against the mark from 100.
SELECT * FROM Assessment, ModuleAssessmentUser WHERE
INNER JOIN moduleassementuser.assessmentID on Assessment.assessmentID
MULTIPLY AssessmentWeighting BY MarkFrom100 AS finalmark
UserID = 1
I know this is way off, but I really don't know how else to go about it.
My SQL knowledge is limited, so any help is appreciated!

You may use a SUM function in your query which will sum all the data of a certain group in a sub query wich will allow you to multiply the sum to the weight
sub query :
SELECT ModuleID, AssessmentID, UserID, SUM(MarkFrom100) as Total
FROM Table_2
GROUP BY ModuleID
Then use this sub query as a table in a main query :
SELECT T1.Assessment_ID, T1.ModuleID, Q1.UserID (Q1.Total * T1.Assessment_Weighting) as FinalMark
FROM (SELECT ModuleID, UserID, SUM(MarkFrom100) as Total
FROM Table_2
GROUP BY ModuleID) AS Q1
INNER JOIN Table_1 as T1 on T1.ModuleID = Q1.ModuleID
-- WHERE T1.ModuleID = 2 -- a particular module ID
GROUP BY ModuleID;
Note that the WHERE statement is in comment. If you want the whole data, remove it, if you want a particular data, use it ^^
NOTE :
I don't have your database, so it may need some tweeks, but the main idea is there

Related

SQL SELECT WHERE IN another SELECT with GROUP_CONCAT

Good Day,
I have 3 Tables - Ticket, Ticket Batch (Multiple Ticket Rows To One Batch) and Ticket Staff (Multiple Staff Rows To One Ticket) and wish to ultimately UPDATE the ticket_batch table with the COUNT of all staff working on tickets per ticket batch.
The tables with applicable columns look as follows
ticket:
| ticket_number | recon_number |
ticket_batch:
| recon_number |
ticket_staff:
| ticket_number |
So I have written the following SQL query to essentially first if I do get the COUNT:
SELECT COUNT(*)
FROM ticket_staf
WHERE ticket_staff.ticket_number IN (SELECT GROUP_CONCAT(ticket.ticket_number) FROM ticket WHERE ticket.recon_number = 1);
Which the query just keeps running, but when I execute the queries separately:
SELECT GROUP_CONCAT(ticket.ticket_number)
FROM ticket
WHERE ticket.recon_number = 1;
I get 5 ticket numbers within split seconds and if I paste that string in the other portion of the query:
SELECT COUNT(*)
FROM ticket_staff
WHERE ticket_staff.ticket_number IN (1451,1453,1968,4457,4458);
It returns the correct COUNT.
So ultimately I guess can I not write queries with GROUP_CONCATS into another SELECT WHERE IN? And how should I structure my query?
Thanks for reading :)
I prefer Inner join as follows:
SELECT COUNT(distinct ts.*)
FROM ticket_staff ts
LEFT JOIN ticket t
ON ts.ticket_number = t.ticket_number
WHERE t.recon_number = 1;
GROUP_CONCAT() doesn't look right. I suspect you are confusing a list of values for IN with a string. They are not the same thing.
In general, I would recommend EXISTS over IN anyway:
SELECT COUNT(*)
FROM ticket_staff ts
WHERE EXISTS (SELECT 1
FROM ticket t
WHERE ts.ticket_number = t.ticket_number AND
t.recon_number = 1
);
For this query, you want an index on ticket(ticket_number, recon_number). However, I am guessing that ticket(ticket_number) is the primary key, which is enough of an index by itself.

Need sql query to pull back data that meets several groups of criteria from same table in one query

I need to write an sql query that will pull back the data that meets several groups of criteria from the same table. The easiest way to describe is to imagine using an SQL "in" clause but instead of the internals of that clause being "or"s joining the parameters you want it to match it is instead an "and".
I attempted to use count to verify the correct amount of data was pulled back for each "in" statement but the count can't always be trusted due to other entries being similar for each column.
A sample table might be this:
id count animal
--- ----- ------
1 5 puppy
1 6 cat
1 6 puppy
So, now I need a query that will pull back all entries with an id of 1 and a count of 5 and 6 and an animal of puppy and cat. I pretty much need to verify the entire path of the table entry to know I want to pull it back. Is there any built in function that can do this? Do I need to use a recursive CTE to dig deep after confirming that one set of criteria is met? Thanks for any help.
If I got it right
with cnt as(
select id
from tbl
where [count] in (5,6) and animal in ('puppy', 'cat')
group by id
having count(distinct[count])=2 and count(distinct animal)=2
)
select id, [count], animal
from tbl
where id in (select id from cnt);
It's kind of confusing what you're looking for exactly but can you not use or's and ands?
select id, count, animal
from table
where id = 1 and
(count = 5 or count = 6) and
(animal = puppy or anmial = cat)
I think you just want:
select t.*
from t
where id = 1 and
count in (5, 6) and
animal in ('puppy', 'cat');
EDIT:
If you want them all in the same row, just rearrange the conditions:
select t.*
from t
where id = 1 and
( (count = 5 and animal = 'puppy') or
(count = 6 and animal = 'cat')
);

how can I calculate the sum of my top n records in crystal report?

I m using report tab -> group sort expert-> top n to get top n record but i m getting sum of value in report footer for all records
I want only sum of value of top n records...
In below image i have select top 3 records but it gives sum of all records.
The group sort expert (and the record sort expert too) intervenes in your final result after the total summary is calculated. It is unable to filter and remove rows, in the same way an ORDER BY clause of SQL cannot effect the SELECT's count result (this is a job for WHERE clause). As a result, your summary will always be computed for all rows of your detail section and, of course, for all your group sums.
If you have in mind a specific way to exlude specific rows in order to appear the appropriate sum the you can use the Select Expert of Crystal Reports to remove rows.
Alternatively (and I believe this is the best way), I would make all the necessary calculations in the SQL command and I would sent to the report only the Top 3 group sums (then you can get what you want with a simple total summary of these 3 records)
Something like that
CREATE TABLE #TEMP
(
DEP_NAME varchar(50),
MINVAL int,
RMAVAL int,
NETVAL int
)
INSERT INTO #TEMP
SELECT TOP 3
T.DEP_NAME ,T.MINVAL,T.RMAVAL,T.NETVAL
FROM
(SELECT DEP_NAME AS DEP_NAME,SUM(MINVAL) AS MINVAL,SUM(RMAVAL) AS
RMAVAL,SUM(NETVAL) AS NETVAL
FROM YOURTABLE
GROUP BY DEP_NAME) AS T
ORDER BY MINVAL DESC
SELECT * FROM #TEMP

SQL Server Sum multiple rows into one - no temp table

I would like to see a most concise way to do what is outlined in this SO question: Sum values from multiple rows into one row
that is, combine multiple rows while summing a column.
But how to then delete the duplicates. In other words I have data like this:
Person Value
--------------
1 10
1 20
2 15
And I want to sum the values for any duplicates (on the Person col) into a single row and get rid of the other duplicates on the Person value. So my output would be:
Person Value
-------------
1 30
2 15
And I would like to do this without using a temp table. I think that I'll need to use OVER PARTITION BY but just not sure. Just trying to challenge myself in not doing it the temp table way. Working with SQL Server 2008 R2
Simply put, give me a concise stmt getting from my input to my output in the same table. So if my table name is People if I do a select * from People on it before the operation that I am asking in this question I get the first set above and then when I do a select * from People after the operation, I get the second set of data above.
Not sure why not using Temp table but here's one way to avoid it (tho imho this is an overkill):
UPDATE MyTable SET VALUE = (SELECT SUM(Value) FROM MyTable MT WHERE MT.Person = MyTable.Person);
WITH DUP_TABLE AS
(SELECT ROW_NUMBER()
OVER (PARTITION BY Person ORDER BY Person) As ROW_NO
FROM MyTable)
DELETE FROM DUP_TABLE WHERE ROW_NO > 1;
First query updates every duplicate person to the summary value. Second query removes duplicate persons.
Demo: http://sqlfiddle.com/#!3/db7aa/11
All you're asking for is a simple SUM() aggregate function and a GROUP BY
SELECT Person, SUM(Value)
FROM myTable
GROUP BY Person
The SUM() by itself would sum up the values in a column, but when you add a secondary column and GROUP BY it, SQL will show distinct values from the secondary column and perform the aggregate function by those distinct categories.

in sql how to return single row of data from more than one row in the same table

I have a single table of activities, some labelled 'Assessment' (type_id of 50) and some 'Counselling' (type_id of 9) with dates of the activities. I need to compare these dates to find how long people wait for counselling after assessment. The table contains rows for many people, and that is the primary key of 'id'. My problem is how to produce a result row with both the assessment details and the counselling details for the same person, so that I can compare the dates. I've tried joining the table to itself, and tried nested subqueries, I just can't fathom it. I'm using Access 2010 btw.
Please forgive my stupidity, but here's an example of joining the table to itself that doesn't work, producing nothing (not surprising):
Table looks like:
ID TYPE_ID ACTIVITY_DATE_TIME
----------------------------------
1 9 20130411
1 v 50 v 20130511
2 9 20130511
3 9 20130511
In the above the last two rows have only had assessment so I want to ignore them, and just work on the situation where there's both assessment and counselling 'type-id'
SELECT
civicrm_activity.id, civicrm_activity.type_id,
civicrm_activity.activity_date_time,
civicrm_activity_1.type_id,
civicrm_activity_1.activity_date_time
FROM
civicrm_activity INNER JOIN civicrm_activity AS civicrm_activity_1
ON civicrm_activity.id = civicrm_activity_1.id
WHERE
civicrm_activity.type_id=9
AND civicrm_activity_1.type_id=50;
I'm actually wondering whether this is in fact not possible to do with SQL? I hope it is possible? Thank you for your patience!
Sounds to me like you only want to get the ID numbers where you have a TYPE_ID entry of both 9 and 50.
SELECT DISTINCT id FROM civicrm_activity WHERE type_id = '9' AND id IN (SELECT id FROM civicrm_activity WHERE type_id = '50');
This will give you a list of id's that has entries with both type_id 9 and 50. With that list you can now go and get the specifics.
Use this SQL for the time of type_id 9
SELECT activity_date_time FROM civicrm_activity WHERE id = 'id_from_last_sql' AND type_id = '9'
Use this SQL for the time of type_id 50
SELECT activity_date_time FROM civicrm_activity WHERE id = 'id_from_last_sql' AND type_id = '50'
Your query looks OK to me, too. The one problem might be that you use only one table alias. I don't know, but perhaps Access treats the table name "specially" such that, in effect, the WHERE clause says
WHERE
civicrm_activity.type_id=9
AND civicrm_activity.type_id=50;
That would certainly explain zero rows returned!
To fix that, use an alias for each table. I suggest shorter ones,
SELECT A.id, A.type_id, A.activity_date_time,
B.type_id, B.activity_date_time
FROM civicrm_activity as A
JOIN civicrm_activity as B
ON A.id = B.id
WHERE A.type_id=9
AND B.type_id=50;