I have a table of the following:
1 X 10
2 X 30
3 Y 5
4 Y 2
...etc
I need to turn it into:
X 300 //(10 * 30)
Y 10 //(5 * 2)
so I'm in fact looking for a kind of a multiplication function that I could use like sum, avg and stuff... does this exist guys?
for instance:
select field2, **multiply**(field3)
from t
group by field2
Thanks
Ideally, Access SQL would have a PRODUCT aggregate function available, but it doesn't. We can however simulate it by remembering what we learned about logarithms at school (or not...), and remembering that the anti-log of the sum of logs is equal to the product:
SELECT field2, EXP(Sum(LOG(Field3))) AS ProductOfField3
FROM t
GROUP BY Field2
Note that whereas a true PRODUCT function would simply return 0 for a group if there are any zero values, this solution will fail if there are any zero values, so watch out for that. Also, this approach won't work if there are any negative values.
To deal with zeroes we could do this:
SELECT
field2,
EXP(Sum(LOG(IIf(Field3 = 0, 1, Field3)))) AS ProductOfField3,
MIN(ABS(Field3)) AS MinOfAbsField3
FROM t
GROUP BY Field2
and then disregard the ProductOfField3 value for any row where MinOfAbsField3 is zero (as this indicates a group containing a zero, thus the 'true' product should be 0)
To deal with negative values we could further do this:
SELECT
field2,
EXP(Sum(LOG(IIf(Field3 = 0, 1, ABS(Field3))))) AS ProductOfField3,
MIN(ABS(Field3)) AS MinOfAbsField3,
SUM(IIf(Field3 < 0, 1, 0)) AS SumOfNegativeIndicator
FROM t
GROUP BY Field2
and interpret the results with these rules:
If MinOfAbsField3 is zero, disregard ProductOfField3 for that row - the product is zero
Otherwise, the required answer for a given row is ProductOfField3, negated if SumOfNegativeIndicator is odd in that row
You can define following two functions:
Public Function ResetProd() As Boolean
Call Prod(Null)
ResetProd = True
End Function
Public Function Prod(nNumber As Variant) As Double
Static nPrevNumber As Double
If IsNull(nNumber) Then
nPrevNumber = 1
Else
nPrevNumber = nPrevNumber * nNumber
End If
Prod = nPrevNumber
End Function
...and use them as follows:
SELECT PROD(_column_for_wich_you_want_product_) FROM _your_table_
WHERE RESETPROD()
Related
I got the following table and I need to return 1 if all rows have disponibilidad = 1
The following QUERY works just fine, but i was looking for a more efficient way of doing it.
QUERY:
SELECT IF(AVG(disponibilidad) < 1, 0, 1) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1;
RESULT:
As I see it, with an 'AND' it would be far more efficient, since it wouldn't have to do AVG().
MySql does not support a boolean AND aggregate function like Postgresql's bool_and.
Why not a simple MIN():
SELECT MIN(disponibilidad) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1;
This will return 1 only if all values of the column are 1 (provided the column is not nullable) and 0 if there is at least one row with 0.
How about something like
SELECT IF(COUNT(*)>0,0,1) AS newResult
FROM pasteleria.compone
RIGHT JOIN pasteleria.ingredientes
ON pasteleria.compone.id_ingrediente = pasteleria.ingredientes.id_ingrediente
WHERE id_componente = 1
AND disponibilidad <> 1
so that if there are any rows where disponibilidad is not 1, you output 0, otherwise if it's zero (so all disponibilidad values are 1) you output 1?
I have a query which sums field 'value' from rows with foreign key value V1 and divides that sum with sum of the field 'value' from rows with foreign key value V2. Somehow I am getting wrong results. What am I doing wrong here?
SELECT
iv1.year,
1,
iv1.country_code,
SUM(iv1.value) / SUM(iv2.value) AS value, # Formula
'Added using stored procedure for creation of 1 indicator as ratio of 2 over 6 indicators' AS additional_info
FROM
indicators_values iv1
JOIN indicators i1 ON (i1.no_of_indicator IN('B1.1.2.3', 'B1.2.2.2')
AND iv1.indicator_id = i1.indicator_id
AND i1.extracted_from_file_type = 'consolidated-a')
JOIN indicators_values iv2 ON (iv2.country_code = iv1.country_code AND iv2.year = iv1.year)
JOIN indicators i2 ON (i2.no_of_indicator IN('B1.1.2.2', 'B1.1.2.3', 'B1.1.2.4', 'B1.2.2.1', 'B1.2.2.2', 'B1.2.2.3')
AND iv2.indicator_id = i2.indicator_id
AND i2.extracted_from_file_type = 'consolidated-a')
WHERE
1=1
AND iv1.country_code = 'AT'
AND i1.no_of_indicator IN('B1.1.2.3', 'B1.2.2.2')
AND i2.no_of_indicator IN('B1.1.2.2', 'B1.1.2.3', 'B1.1.2.4', 'B1.2.2.1', 'B1.2.2.2', 'B1.2.2.3')
GROUP BY
iv1.year, iv1.country_code;
I know that I am getting wrong results, because most of the results that I am getting are bigger than 1, and they should all be smaller than 1, since I should have in the denominator same values contained in the numerator, plus some additional ones. Please advise? Thanks!
Schematically (too lazy to understand your conditions - maybe something is missing or changed places):
SELECT iv.year,
iv.country_code,
( SUM(CASE WHEN i.no_of_indicator IN('B1.1.2.3', 'B1.2.2.2')
THEN iv.value
END)
/
SUM(CASE WHEN i.no_of_indicator IN('B1.1.2.2', 'B1.1.2.3', 'B1.1.2.4', 'B1.2.2.1', 'B1.2.2.2', 'B1.2.2.3')
THEN iv.value
END
) AS value
FROM indicators_values iv
JOIN indicators i ON iv.indicator_id = i.indicator_id
WHERE i.extracted_from_file_type = 'consolidated-a'
AND iv.country_code = 'AT'
GROUP BY iv.year, iv.country_code
PS. Divisor may formally be zero - take care not to get a division by zero error.
I am stuck in a query I want to store sum result in a variable where status = 3, what happening right now is it store the value of last row and show it with all rows
Here is the query
SELECT
request_made_on,driver_id,
#sum_result = SUM(status = 3) AS complete_count,#sum_result,
SUM(status = 6) AS missed_count,
(status = 4) AS canceled_count,
sum(actual_fare),sum(discount)
from tb_engagements
group by date(request_made_on),driver_id;
and here is the screenshot,
second screenshot
I'm guessing that you want the sum of all the values:
select request_made_on, driver_id,
(#sum_result := #sum_result + SUM(status = 3)) AS complete_count,
sum(status = 6) AS missed_count,
sum(status = 4) AS canceled_count,
sum(actual_fare),
sum(discount)
from tb_engagements c cross join
(select #sum_result := 0) params
group by date(accept_time), driver_id;
Notes:
You don't need to return the value of the variable as well as the expression. The expression adds a column to the result set with the value.
You don't need if() to count values. MySQL has a nice short-hand, treating boolean expressions as integers in a numeric context.
I currently have an Access query that returns data in two forms
One form is 5 numbers, e.g., 12345
The other form is 2 letters, followed by 5 numbers, e.g., ab12345
This is coming in the same field, and I need to get only the numbers. I can't strip off the first two characters, because then for the IDs that have only the numbers, I'm cutting it short.
Use Val(string) to strip letters after numbers.
Use pVal(string) to strip letters before numbers.
string1 = "123456abcd1234"
val1 = val(string1) => val1 = 123456
string2 = "aqweqweasd123456abcd1234"
val2 = pval(string2) => val2 = 123456
if in case you have "asdasd123asasd456" and you want to have 123456 as result you can modify the pval to replace all non numeric values from output
here is the pVal function. Place this in a module and use it from anywhere
Public Function pVal(s As String)
Dim i As Long
For i = 1 To Len(s)
If IsNumeric(Mid(s, i, 1)) Then
pVal = Val(Mid(s, i, Len(s)))
Exit Function
End If
Next i
End Function
Use a select query as source for your form like this with an expression that strips the two leading characters:
Select *, Mid([XX0000NumberField], 3) As NumberOnlyID
From YourTable
Or for mixed numbers:
Select *, Right([XX0000NumberField], 5) As NumberOnlyID
From YourTable
I am trying to use a expression within an expression in SSRS and it's getting really complicated. Is there a way around this?
For example if I have a number of sales and number of contacts I can create the conversion rate by dividing the sales into the contacts ie
=fields!sales.value/fields!contacts.value
What I want to do next is use this to put the sales people into various bands so that those with a conversion rate in thresholds are displayed in bandings.
=iif(fields!sales.value/fields!contacts.value<0.5,"poor","Ok")
This is fine for 2 bandings (ok and poor), but gets more complicated for the 5 bandings I want.
I must be able to define the first variable and then use that within the iif statement?
How do I do this in SSRS 2008?
Thanks in advance.
Better to use Switch which returns the first true condition
=Switch(
fields!sales.value/fields!contacts.value < value1, "very poor",
fields!sales.value/fields!contacts.value < value2, "poor",
...
fields!sales.value/fields!contacts.value < value(n-2), "good",
fields!sales.value/fields!contacts.value < value(n-1), "very good",
True, "excellent"
)
where value1 < value2 < ... < valuen.
The final True is dummy like the use of default in an SQL Case expression
An alternative is using custom vb code you can create a function
Public Function GetRating( ByVal rating As Decimal ) As String
Select Case rating
Case Is < value1
Return "poor"
...
Case Is < valuen
return "very good"
Case Else
Return "excellent"
End Function
Then in the rows use the expression
= Code.GetRating( fields!sales.value/fields!contacts.value )