Evaluation of nested IF in MySQL - mysql

I found this code in a WordPress plugin, but I cannot understand what does it mean or how it can be read.
Can somebody to help me underdstaint this code :?
IF(agr_sam_ads.ad_users = 0, TRUE, IF(agr_sam_ads.ad_users_reg = 1, IF(agr_sam_ads.x_ad_users = 1, NOT FIND_IN_SET("admin", agr_sam_ads.x_view_users), TRUE ....
I have not paste the whole query because it is huge. In what I am interested to be helped is the part of the Query that looks like that:
IF(expression, value, IF(expression, IF(expression, SQL Logical Query, value ...
I have not see this syntax, and I don't know where to search for that. In MySQL documentation the IF statement syntax is like that : http://dev.mysql.com/doc/refman/5.0/en/if.html and it is not looks like the one I have paste above.
Just for the users are interested in the full code, the code is here:
SELECT
agr_sam_places.id,
agr_sam_places.name,
agr_sam_places.description,
agr_sam_places.code_before,
agr_sam_places.code_after,
agr_sam_places.place_size,
agr_sam_places.place_custom_width,
agr_sam_places.place_custom_height,
agr_sam_places.patch_img,
agr_sam_places.patch_link,
agr_sam_places.patch_code,
agr_sam_places.patch_adserver,
agr_sam_places.patch_dfp,
agr_sam_places.patch_source,
agr_sam_places.trash,
(
SELECT
COUNT(*)
FROM
agr_sam_ads
WHERE
agr_sam_ads.pid = agr_sam_places.id
AND
agr_sam_ads.trash IS FALSE
) AS ad_count,
(
SELECT
COUNT(*)
FROM
agr_sam_ads
WHERE
agr_sam_ads.pid = agr_sam_places.id
AND
agr_sam_ads.trash IS FALSE
AND
(
IF(agr_sam_ads.ad_users = 0, TRUE, IF(agr_sam_ads.ad_users_reg = 1, IF(agr_sam_ads.x_ad_users = 1, NOT FIND_IN_SET("admin", agr_sam_ads.x_view_users), TRUE
)
AND
IF(agr_sam_ads.ad_users_adv = 1, (agr_sam_ads.adv_nick <> "admin"), TRUE), FALSE)))
AND
(
(
agr_sam_ads.view_type = 1
)
OR
(
agr_sam_ads.view_type = 0
AND
(
agr_sam_ads.view_pages+0 & 256
)
)
)
AND
(
agr_sam_ads.ad_cats = 0
)
AND
(
agr_sam_ads.ad_authors = 0
)
AND
IF(agr_sam_ads.ad_schedule, CURDATE() BETWEEN agr_sam_ads.ad_start_date AND agr_sam_ads.ad_end_date, TRUE)
AND
IF(agr_sam_ads.limit_hits, agr_sam_ads.hits_limit > agr_sam_ads.ad_hits, TRUE)
AND
IF(agr_sam_ads.limit_clicks, agr_sam_ads.clicks_limit > agr_sam_ads.ad_clicks, TRUE)
AND
(
agr_sam_ads.ad_weight > 0
)
) AS ad_logic_count,
(
SELECT
COUNT(*)
FROM
agr_sam_ads
WHERE
agr_sam_ads.pid = agr_sam_places.id
AND
agr_sam_ads.trash IS FALSE
AND
(
IF(agr_sam_ads.ad_users = 0, TRUE, IF(agr_sam_ads.ad_users_reg = 1, IF(agr_sam_ads.x_ad_users = 1, NOT FIND_IN_SET("admin", agr_sam_ads.x_view_users), TRUE)
AND
IF(agr_sam_ads.ad_users_adv = 1, (agr_sam_ads.adv_nick <> "admin"), TRUE), FALSE)))
AND
(
(
agr_sam_ads.view_type = 1
)
OR
(
agr_sam_ads.view_type = 0
AND
(
agr_sam_ads.view_pages+0 & 256
)
)
)
AND
(
agr_sam_ads.ad_cats = 0
)
AND
(
agr_sam_ads.ad_authors = 0
)
AND
IF(agr_sam_ads.ad_schedule, CURDATE() BETWEEN agr_sam_ads.ad_start_date AND agr_sam_ads.ad_end_date, TRUE)
AND
IF(agr_sam_ads.limit_hits, agr_sam_ads.hits_limit > agr_sam_ads.ad_hits, TRUE)
AND
IF(agr_sam_ads.limit_clicks, agr_sam_ads.clicks_limit > agr_sam_ads.ad_clicks, TRUE)
AND
IF(agr_sam_ads.ad_weight > 0, (agr_sam_ads.ad_weight_hits*10/(agr_sam_ads.ad_weight*1000)) < 1, FALSE)
) AS ad_full_count
FROM
agr_sam_places
WHERE
agr_sam_places.id = 10
AND
agr_sam_places.trash IS FALSE;

It should be read as:
IF (
expression,
valueIfExpressionIsTrue,
valueIfExpressionIsValue
)
So to take part of your code:
IF(
agr_sam_ads.ad_users = 0,
TRUE,
IF(
agr_sam_ads.ad_users_reg = 1,
2,
3
)
)
I see that you're familiar with PHP, so essentially if this was PHP, the code would be
if ($arg_sam_ads_ad_users == 0) {
return true;
} else {
if ($arg_sam_ads_ad_users_reg == 1) {
return 2;
} else {
return 3;
}
}

This is basically creating an IF-ELSE tree without using the IF _ THEN _ ELSE _ ENDIF syntax.
Take the following example:
IF(1=0, 1, IF(1=1, 1, 0))
This is the equivalent of the following with C syntax:
IF (1=0) {
1
}
ELSE IF (1=1) {
1
}
ELSE {
0
}
The more common SQL syntax is the following:
IF 1=0 THEN
1;
ELSEIF 1=1 THEN
1;
ELSE
0;
ENDIF;

Related

withCount() - get difference of 2 counts

I have a table that has a column is_up_vote = true|false
I am trying to write a query using withCount() so it returns me the sum of true values and false values.
select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = true returns 17
select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = false returns 15
However I couldn't figure out how to get different of them, so the total returns 2.
What I tried is:
Model::withCount(['votes' => function($q) {
$q->selectRaw(
'(SUM (COUNT(is_up_vote) WHERE is_up_vote = true) - (COUNT(is_up_vote) WHERE is_up_vote = false) )'
);
}]);
But this returns 17+15 = 32
without SUM(), it's also returning 32.
$q->selectRaw(
'( (COUNT(is_up_vote) WHERE is_up_vote = true) - (COUNT(is_up_vote) WHERE is_up_vote = false) )'
);
What am I doing wrong?
Edit:
If I try one side, it ignores the where and still returns 32, so the where is not getting called (where it does in sql)
return $query->withCount(['votes' => function($q) {
$q->selectRaw('(COUNT(is_up_vote) WHERE is_up_vote = true)');
}]);
maunal sequel query returns 17:
select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = true
Edit 2:
$query->withCount([
'votes as up_votes_count' => function($q) {
$q->where('is_up_vote', true);
},
'votes as down_votes_count' => function($q) {
$q->where('is_up_vote', false);
},
]);
The only thing that I could make work is this, but it'd need extra step for getting the total, so I didn't really like this approach. I'm sure someone more proficient with queries can come up with something with direct query.
withCount may not be able to handle this case. what about using addSelect to calculate the votes count.
return Model::addSelect(['votes_count' => Vote::selectRaw('( (COUNT(is_up_vote) WHERE is_up_vote = true) - (COUNT(is_up_vote) WHERE is_up_vote = false) )')
->whereColumn('parent_id', 'parents.id')
])->get();
I don't know whether the sub-query is gonna work. But you know the idea.
According to the instructions commented by #Jefferson Pessanha, just using Model::selectRaw('(abs(2 * sum(is_up_vote) - count(*)))')->get(); would be enough
create table comment_votes
(
is_up_vote tinyint(1) default 1 null
);
insert into comment_votes values (true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true),(true);
insert into comment_votes values (false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false),(false);
select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = true;
returns 17
select COUNT(is_up_vote) from comment_votes WHERE is_up_vote = false;
returns 15
select (abs(2 * sum(is_up_vote) - count(*))) from comment_votes;
returns 2
Explain:
trueValues + falseValues = total
falseValues = total - trueValues
trueValues - falseValues = x
trueValues - (total - trueValues) = x
2 * trueValues - total = x
trueValues = sum(is_up_vote) [only trues stored as 1 are counted]
total = count(*)
Abs function is to convert the result to positive in case of negative
Isn't it correct?
Try this.
select
sum( if(is_up_vote= true, 1, 0) ) as uptrue,
sum( if(is_up_vote= false, 1, 0) ) as upfalse,
sum( if(is_up_vote= true, 1, -1) ) as updiff
from comment_votes
Edit: 1
Instead of checking if it is true or false, try this.
select
sum( if(is_up_vote, 1, 0) ) as uptrue,
sum( if(is_up_vote, 0, 1) ) as upfalse,
sum( if(is_up_vote, 1, -1) ) as updiff
from comment_votes

Lua - How to use a local variable (image URL) in a function to print an image (loadRemoteImage)?

I have a code in Lua. In the first function, I get a JSON data and put it in a variable (item1), and am able to print it. In the second function, I would like to use this variable to show the image (because item1 is an image URL). I tried a forward declaration like this and put it in the second function, but it does not work. How can this be solved?
local item1
local function networkListener( event )
local res = json.prettify( event.response )
local decoded = json.decode( res )
if ( event.isError ) then
print( "--Network error-- ", ( res ) )
else
print( "Results: " .. ( res ) )
item1 = decoded.results.bindings[0].image.value
print(item1)
local myText = display.newText(sceneGroup, item1, 10, 100, native.systemFont, 26 )
myText:setFillColor( 1, 1, 1 )
end
end
params.body = body
network.request("http://example.com/data.json", "GET", networkListener, params)
local function networkListener2( event )
if ( event.isError ) then
print ( "Network error - download failed" )
else
event.target.alpha = 0
transition.to( event.target, { alpha = 1.0 } )
end
print ( "event.response.fullPath: ", event.response.fullPath )
print ( "event.response.filename: ", event.response.filename )
print ( "event.response.baseDirectory: ", event.response.baseDirectory )
end
display.loadRemoteImage(item1, "GET", networkListener2, "item1.png", system.TemporaryDirectory, 50, 50 )
Thank you very much for your help in advance!
In your code the display.loadRemoteImage() is called before previous network.request() has finished its job. Callback networkListener wasn't triggered yet, so item1 variable is not assigned.
You should schedule loadRemoteImage() from within within networkListener, or anywhere else where you will know that the url was successfully read, i.e. previous request has finished.
local function networkListener2( event )
if ( event.isError ) then
print ( "Network error - download failed" )
else
event.target.alpha = 0
transition.to( event.target, { alpha = 1.0 } )
end
print ( "event.response.fullPath: ", event.response.fullPath )
print ( "event.response.filename: ", event.response.filename )
print ( "event.response.baseDirectory: ", event.response.baseDirectory )
end
local function networkListener( event )
local res = json.prettify( event.response )
local decoded = json.decode( res )
if ( event.isError ) then
print( "--Network error-- ", ( res ) )
else
print( "Results: " .. ( res ) )
item1 = decoded.results.bindings[0].image.value
print(item1)
local myText = display.newText(sceneGroup, item1, 10, 100, native.systemFont, 26 )
myText:setFillColor( 1, 1, 1 )
display.loadRemoteImage(item1, "GET", networkListener2, "item1.png", system.TemporaryDirectory, 50, 50 )
-- Position should be set by the center of the text object
local myText = display.newText(sceneGroup, item1, 10, 300, native.systemFont, 26 )
myText:setFillColor( 1, 1, 1 )
local myText2 = display.newText(sceneGroup, item2, 10, 500, native.systemFont, 26 )
myText:setFillColor( 1, 1, 1 )
end
end
params.body = body
network.request("http://example.com/data.json", "GET", networkListener, params)

Why are these equivalent functions producing a different result?

This is the original method, my intent was to abstract away many of the specifics of the code, to improve readability, by placing the specifics in functions which performed the same action, but with a more readable name.
With this first method I achieve the desired behavior and rows[x] is properly added to lineRows.
def getAllRowsForLine( rows, index ) {
def lineRows = [rows[index]]
def newOperatorNotFound
def x = index + 1
if ( x <= rows.size() - 1 ) {
newOperatorNotFound = true
while ( x <= ( rows.size() - 1 ) && newOperatorNotFound ) {
if ( rows[x].PGM_PROC_OPE.trim() == "" ) {
lineRows << rows[x]
} else if ( rows[x].PGM_PROC_TY == "AN" || rows[x].PGM_PROC_TY == "OR" ) {
lineRows << rows[x]
}
else {
newOperatorNotFound = false
}
x++
}
}
return lineRows
}
Here is the refactored code along with the relative methods for context.
This method is not resulting in the desired behavior, breaking the loop after the first rows[x] is added to lineRows.
def getAllRowsForLine2( rows, index ) {
def lineRows = [rows[index]]
def newOperatorNotFound
def i = index + 1
if ( moreRows( rows, i ) ) {
newOperatorNotFound = true
while ( moreRows( rows, i ) && newOperatorNotFound ) {
if ( operatorEmpty( rows, index ) ) {
lineRows << rows[i]
}
else if ( procTypeAnd( rows, i ) || procTypeOr( rows, i ) ) {
lineRows << rows[i]
} else {
newOperatorNotFound = false
}
i++
}
}
return lineRows
}
def operatorEmpty( rows, index ) {
return rows[index].PGM_PROC_OPE.trim() == ""
}
def procTypeAnd( rows, index ) {
return rows[index].PGM_PROC_TY == "AN"
}
def procTypeOr( rows, index ) {
return rows[index].PGM_PROC_TY == "OR"
}
def moreRows( rows, index ) {
return index <= ( rows.size() - 1 )
}
As far as I can tell these things are equivalent. I ran the below code to attempt testing the equivalency of the functions and it returns true.
println lineProcessor.getAllRowsForLine( rows, 0 ) == lineProcessor.getAllRowsForLine2( rows, 0 )
=> true
Oops, I realized that I had used index in the operatorEmpty function instead of i. If I change index to i the function performs as expected.

How do I achieve this in C#

How do I aggregate conditionally in C#
Like in the following vb code:
Dim movement = From item In dbo.VIEWITEMMOVEMENTs
Where item.DATETRANSFERRED.Value.Date = Me.DateTimePicker1.Value.Date
Group By item.DATETRANSFERRED.Value.Date, item.ITEMDESCRIPTION
Into moved = Group, sold = Sum(item.QUANTITYSOLD), [IN] = Sum(If(item.QUANTITY < 0.0, 0.0, item.QUANTITY)), Out = Sum(If(item.QUANTITY > 0, 0, item.QUANTITY))
Select ITEMDESCRIPTION, sold, [IN], Out Order By ITEMDESCRIPTION Ascending
Me.DataGridView1.DataSource = movement
var result = (
from item in dbo.VIEWITEMMOVEMENTs
where item.DATETRANSFERRED.Value.Date == this.DateTimePicker1.Value.Date
group item by new { item.DATETRANSFERRED.Value.Date, item.ITEMDESCRIPTION }
into g
select new
{
g.Key.ITEMDESCRIPTION,
sold = g.Sum(x => x.QUANTITYSOLD),
IN = g.Sum(x => (x.QUANTITY <0 ? 0 : x.QUANTITY)),
Out = g.Sum(x => (x.QUANTITY > 0 ? 0 : x.QUANTITY))
}
).OrderBy(d => d.ITEMDESCRIPTION);
if you are trying to convert that snippet of code. you could use the converters like
VB to C#
Hope this helps.

EF 4.1 - code first - query no longer works

I moved from using an edmx file to code first. The following query is no longer working (it's basically a group by with limit 1) :
(from sc in dbContext.student_courses
where
sc.student_id == student.id
&& sc.course_id == course.id
&& sc.complete_flag == 1
group sc by new
{
sc.complete_flag,
sc.direct_to_test_flag,
sc.dept_purchase_flag,
sc.issue_ce_flag,
sc.unlimited_purchase_flag,
sc.survey_taken
}
into scgroup
select new StudentCourseDetails
{
completeVideo = scgroup.Max(x => x.complete_flag),
directToTest = scgroup.Max(x => x.direct_to_test_flag),
isDepartmentPurchase = scgroup.Max(x => x.dept_purchase_flag),
issueCE = scgroup.Max(x => x.issue_ce_flag),
isUnlimitedPurchase = scgroup.Max(x => x.unlimited_purchase_flag),
surveyTaken = scgroup.Max(x => x.survey_taken)
}).FirstOrDefault();
The resulting sql :
SELECT `Limit1`.`complete_flag`,
`Limit1`.`C1`,
`Limit1`.`C2`,
`Limit1`.`C3`,
`Limit1`.`C4`,
`Limit1`.`C5`,
`Limit1`.`C6`
FROM (SELECT `GroupBy1`.`A1` AS `C1`,
`GroupBy1`.`A2` AS `C2`,
`GroupBy1`.`A3` AS `C3`,
`GroupBy1`.`A4` AS `C4`,
`GroupBy1`.`A5` AS `C5`,
`GroupBy1`.`A6` AS `C6`,
`GroupBy1`.`K1` AS `complete_flag`
FROM (SELECT Max(`complete_flag`) AS `A1`,
Max(`direct_to_test_flag`) AS `A2`,
Max(`dept_purchase_flag`) AS `A3`,
Max(`issue_ce_flag`) AS `A4`,
Max(`unlimited_purchase_flag`) AS `A5`,
Max(`survey_taken`) AS `A6`
FROM `student_courses` AS `Extent1`
WHERE ((`Extent1`.`student_id` = 3885 /* #p__linq__0 */)
AND (`Extent1`.`course_id` = 606 /* #p__linq__1 */))
AND (1 = `Extent1`.`complete_flag`)
GROUP BY `Extent1`.`complete_flag`,
`Extent1`.`dept_purchase_flag`,
`Extent1`.`direct_to_test_flag`,
`Extent1`.`issue_ce_flag`,
`Extent1`.`survey_taken`,
`Extent1`.`unlimited_purchase_flag`) AS `GroupBy1`
LIMIT 1) AS `Limit1`
The problem is that when it adds the limit 1, it also adds an extra column :
GroupBy1.K1 AS complete_flag - which doesn't exist.
Any thoughts ?