I have a table that looks like
ID Name amount
1 x 10
2 y 20
3 z 30
I want to count the number of IDs and sum the amounts.
I tried
SELECT COUNT(table.ID) as NumberOfIds and SUM(table.AMOUNT)
FROM table
but I keep getting an error that I'm missing my where statement. Neither of these functions require a where statement by themselves, so why is it asking for one when they are together?
You don't use and to specify multiple desired results, you use commas.
Try this:
SELECT COUNT(table.ID) as NumberOfIds, SUM(table.AMOUNT) as SumOfAmounts
FROM table
Related
I have a long database of observations for individuals. There are multiple observations for each individual, all assigned different medcodeid's.
I want to extract all records of individuals with certain medcodeid's assigned, but only if they at some point have had a smaller list of specific codes assigned.
This is an example of what I start with:
long dataset, multiple observations
and this is the records I'd like to extract:
multiple observations, but patients 3 and 5 are not extracted, as they never had a medcode 12
Would this be an additional WHERE clause? I am struggling as this will then only extract the second AND medcodeid list. But I want it to extract all, if the individual has had one of these certain fewer codes at some point. I hope that makes some sense. I am unfamiliar with IF command? And cannot see how CASE WHEN would work either.
Thank you very much in advance!
You definitely don't want to filter out all the rows so you're right that an additional condition won't help with that. And where only lets you look at the current row and you're trying to make a decision based all the rows belonging to the patient.
This query just uses a table expression and an analytic count() that tags each row with the number of matches as it lets you look outside the current row just like you need.
-- my additions to your query are in lowercase
with data as (
SELECT obs.patid, yob, obsdate, medcodeid,
count(case when medcodeid IN (<list of mandatory codes>) then 1 end)
over (partition by obs.patid) as medcode_count
-- assuming the relationship looks something like this
from obs inner join medcode on medcode.patid = obs.patid
WHERE medcodeid IN (<list of codes>)
AND obsdate BETWEEN '2004-12-31' AND GETDATE()
AND patienttypeid = 3 AND acceptable = 1 AND gender = 2
AND YEAR(obsdate) - yob > 15 AND YEAR(obsdate) - yob < 45
)
select * from data where medcode_count > 0;
At first I thought you were requiring that at least five of the codes from the full set were found. Now that you've edited the question I believe that you want to require that at least one code from a smaller subset is present. Either way this approach will work.
If I'm understanding what you're asking, I think what you need is an additional WHERE clause with a subquery. This could be done with and EXIST or a join but I find an IN query to be easier to work with.
You left the FROM out of your query so I had to guess at it but try this:
SELECT
obs.patid,
yob,
obsdate,
medcodeid
FROM
obs
WHERE
medcodeid IN (list of 20 codes)
AND (obsdate BETWEEN '2004-12-31' AND GETDATE())
AND patienttypeid = 3
AND acceptable = 1
AND gender = 2
AND ((YEAR(obsdate))-yob) > 15
AND ((YEAR(obsdate)) - yob) < 45
AND obs.patid IN (
SELECT
obs.patid
FROM
obs
WHERE
medcodeid IN (5 of the 20 codes)
);
I have a report which has a transaction type as a row group. There are two different types. I want to get the percentage of one type 2 compared to type 1.
I am not sure how to do this, I assume I need to use an expression which states the name of the transaction type and then make a calculation based on the other type.
So Instead of a total for July being 300, I would like the percentage of SOP+ compared to SOP-, so in this case 1.96%. For clarity, the figures in SOP+ are not treated as negative.
When you design a query to be used in a report, it is generally easier to work with different types of values being in separate columns. You can let the report do most of the grouping and aggregation for you. In that case, the expression would be something like this:
=Fields!SOP_PLUS.Value / Fields!SOP_MINUS.Value
Since they are both in rows in the same column, you have to use some logic to separate them out into columns and then do the operation.
You'll need to add two calculated fields to your dataset. Use an expression like this to get the values:
=IIf(Fields!TYPE_CODE.Value = "SOP+", Fields!SOP.Value, Nothing)
In other words, you will have new columns that have just the plus and minus values with blanks in the other rows. Now you can use a similar expression to earlier to compare them.
=Max(Fields!SOP_PLUS.Value) / Max(Fields!SOP_MINUS.Value)
Keep in mind that the Max function applies to the current group scope. When you add in multiple row and column groups to the mix this can get more complicated. If that becomes an issue, I would suggest looking at rewriting the query to provide these values in separate rows to make the report design easier.
WITH table1([sop-], [sop+]) AS (
SELECT 306, -6
UNION ALL
SELECT 606, -14)
SELECT(CAST([sop+] AS DECIMAL(5, 2)) / CAST([sop-] AS DECIMAL(5, 2))) * 100.0 FROM table1;
Returns :
-1.960784000
-2.310231000
I have a indexed table where one of the indexed columns can contains data with an underscore.
ID Name
1 01_A3L
2 02_A3L
3 03_A3L
4 05_A3L
5 some name
6 another name
7 a name
When I search this table with the following query however I don't get any results:
SELECT * FROM MyAmazingTable WHERE( CONTAINS(*,'"a3l*"'))
What is the reason for this? And how can I make sure I do get results I expect (all records that end with A3L)?
Kees C Bakker is 100% correct, but if you just wanted to get the results you require without all of the steps.
The quick/dirty way to do so would be change your search to be a like...
Select * from MyAmazingTable where Name like '%A3L'
The % in this case would represent whatever comes before and make sure the last 3 characters are A3L.
Which will give you the results that you are looking for.
I am trying to calculate totals for each row as well as a percentage of the overall total.
Right now I have a table like this:
Blah Col1 Col2 Col3
-----------------------------
ABC 1 1 1
DEF 2 2 3
-----------------------------
Total 3 3 4
And I want it to include totals/percentages like so:
Blah Col1 Col2 Col3 Total %
--------------------------------------------
ABC 1 1 1 3 30%
DEF 2 2 3 7 70%
--------------------------------------------
Total 3 3 4 10 100%
I know I can do the calculations in the SQL query, but the stored procedure is rather complicated so I'd like to avoid that if possible. So I'm wondering if there's a simple way to achieve this in SSRS.
Right now I just have a row group for each Blah which I use to calculate column totals.
I added a Totals Row for my matrix, then I referenced the totals textbox (textbox 8 in my case) for the column and I did:
Sum(Fields.FieldName.Value)/ReportItems!Textbox8.Value
I hope this makes sense!
To calculate the total, just do a simple sum using the + operator. For the percentage, you can refer to the grand total using ReportItems!ItemName.
You can use aggregate functions in Reporting Services like "SUM" and "AVG" to achieve what you are trying to do. The way it works is "Detail" parts of groups in SSRS tables will list all of the data, while non-detail parts (like headers and footers) of groups can be used for aggregates like:
=SUM(Fields!TestValue.Value)
http://msdn.microsoft.com/en-us/library/ms159134%28v=sql.90%29.aspx
Let me know if you need any more help.
Create two groups, one on a column that is the same data for each row, then one on column blah. add a row for the emcompassing group and do a sum there.
you can simply do as following:
Sum(CInt(Fields!TestValue.Value))
or Sum(CInt(Fields!DollarAmountOfCheck.Value),"DataSet1")
sometime when data is coming through WCF, it does not accept Sum() function. but this works fine in that case.
i have a mysql table set up like so:
id uid keywords
-- --- ---
1 20 corporate
2 20 corporate,business,strategy
3 20 corporate,bowser
4 20 flowers
5 20 battleship,corporate,dungeon
what i WANT my output to look like is:
20 corporate,business,strategy,bowser,flowers,battleship,dungeon
but the closest i've gotten is:
SELECT DISTINCT uid, GROUP_CONCAT(DISTINCT keywords ORDER BY keywords DESC) AS keywords
FROM mytable
WHERE uid !=0
GROUP BY uid
which outputs:
20 corporate,corporate,business,strategy,corporate,bowser,flowers,battleship,corporate,dungeon
does anyone have a solution? thanks a ton in advance!
What you're doing isn't possible with pure SQL the way you have your data structured.
No SQL implementation is going to look at "Corporate" and "Corporate, Business" and see them as equal strings. Therefore, distinct won't work.
If you can control the database,
The first thing I would do is change the data setup to be:
id uid keyword <- note, not keyword**s** - **ONE** value in this column, not a comma delimited list
1 20 corporate
2 20 corporate
2 20 business
2 20 strategy
Better yet would be
id uid keywordId
1 20 1
2 20 1
2 20 2
2 20 3
with a seperate table for keywords
KeywordID KeywordText
1 Corporate
2 Business
Otherwise you'll need to massage the data in code.
Mmm, your keywords need to be in their own table (one record per keyword). Then you'll be able to do it, because the keywords will then GROUP properly.
Not sure if MySql has this, but SQL Server has a RANK() OVER PARTITION BY that you can use to assign each result a rank...doing so would allow you to only select those of Rank 1, and discard the rest.
You have two options as I see it.
Option 1:
Change the way your store your data (keywords in their own table, join the existing table with the keywords table using a many-to-many relationship). This will allow you to use DISTINCT. DISTINCT doesn't work currently because the query sees "corporate" and "corporate,business,strategy" as two different values.
Option 2:
Write some 'interesting' sql to split up the keywords strings. I don't know what the limits are in MySQL, but SQL in general is not designed for this.