Coldfusion: SELECT FROM QoQ WHERE X in (SELECT Y FROM QoQ) not working - sql

In CF I am trying to do a QoQ where the rows are in a list of other rows. Basically moving some code from cftags to cfscript (Not important why). In tags we have a main query and we have several nests that do some heavy lifting. I am moving this to cfscript and have the following syntax that is working:
var submissionList = new Query(dbtype="query", QoQsrcTable=ARGUMENTS.answers, sql="
SELECT submission_id FROM QoQsrcTable GROUP BY submission_id
").execute().getResult();
var submissions = new Query(dbtype="query", QoQsrcTable=ARGUMENTS.answers, sql="
SELECT * FROM QoQsrcTable WHERE submission_id IN (#submissionList.submission_id#)
").execute().getResult();
I have tried the following but it fails to work:
var submissions = new Query(dbtype="query", QoQsrcTable=ARGUMENTS.answers, sql="
SELECT * FROM QoQsrcTable WHERE submission_id IN (SELECT submission_id FROM QoQsrcTable GROUP BY submission_id)
").execute().getResult();
I think the second example should work. I've tried messing with it in various ways. But can't seem to figure out what I am doing wrong. Maybe a nested QoQ doesn't work like that. Is there another way I can accomplish what I am trying without two chunks of code? Just so it's more readable and I don't have to assign variables twice.

QoQ doesn't support subqueries. That's the long and the short of it.
Docs

In Coldfusion 10 or Railo 4, you can utilize the groupBy function of Underscore.cfc to accomplish what you want in much less code:
_ = new Underscore();// instantiate the library
submissions = _.groupBy(arguments.answers, 'submission_id');
groupBy() returns a structure where the keys are the values of the group element (in this case, submission_id).
(Disclaimer: I wrote Underscore.cfc)

Related

Add Math function to SQL Query

New to SQL and I am trying to run a query that pulls all our item codes, lot number, and qty on hand.
Each lot number has multiple entries due to adjustments. I need a way of running my query and having it add or subtract to get the actual qty on hand for each lot and only show me lots that are in the negatives. I have tried playing with SSRS but I cant get it right. I'm using SQL 2008R2.
SELECT
IMLAYER.ITEM_CODE
,IMMSTR.ITEM_DESC
,IMLAYER.LOT_NO
,IMLAYER.QTY_ON_HAND
FROM
IMLAYER
INNER JOIN
IMMSTR
ON
IMLAYER.ITEM_CODE = IMMSTR.ITEM_CODE
WHERE
(IMLAYER.QTY_ON_HAND < 0);
I believe I understand the requirements correctly, but if not please comment and I can update the query:
SELECT
M.ITEM_CODE
,M.ITEM_DESC
,L.LOT_NO
,'SUM_OF_QTY_ON_HAND' = SUM(L.QTY_ON_HAND)
FROM
IMLAYER L
INNER JOIN
IMMSTR M
ON L.ITEM_CODE = M.ITEM_CODE
GROUP BY
M.ITEM_CODE
,M.ITEM_DESC
,L.LOT_NO
HAVING
SUM(L.QTY_ON_HAND) < 0
HAVING is the trick you are looking for to be able to use an aggregate function for filtering.

What is the purpose of "#*" hash and star symbols before the parameters passed to a query?

I have the following query which gets called from ASP.NET application and creates a subset of rows within the same table "DETAILS" and the subset is defined by parameters $f2 and $f3 used for paging purposes.
INSERT INTO DETAILS (ID, UIN, ACTIVE_IND, UGUID, CREATED_BY, CREATED_DATE)
SELECT AF.ID, AF.UIN, AF.ACTIVE, AF.UGUID, AF.CREATED_BY, AF.CREATED_DATE FROM
(SELECT #*$f0 ID, DET.UIN, DET.ACTIVE_IND, DET.UGUID, DET.CREATED_BY, DET.CREATED_DATE,
DENSE_RANK() OVER (ORDER BY P.PRODUCT_ID) FG
FROM DETAILS DET
JOIN PRODUCTS P ON P.UIN = DET.UIN
WHERE ID = #*$f1 ) AF
WHERE AF.FG BETWEEN #*$f2 AND #*$f3
The ASP.NET c# code that calls this query looks like this
new SqlDataSource().ExecuteSql("InsertDetails",
new List<object>() {_subSetId, _mainSetId, start, end});
"InsertDetails" is the name of the above query and "start" "end" are the paging range.
My question is: What function or purpose have the "#*" before the parameters in this query??. I need to replicate this query for other tables but would like to know why are the parameters passed like this "#*$f0", "#*$f1", "#*$f2" and "#*$f3".
You asked me to put my comment as answer. It seems that I had the correct guess:
Sometimes such weird characters are used as place holders which are
replaced on string level before the call (kind of dynamic command
generation)... Neither beautifull nor clean, but sometimes - well -
you know...
You might use the profiler to monitor the statement which
is processed acutally
Happy Coding!

Selecting rows from Parent Table only if multiple rows in Child Table match

Im building a code that learns tic tac toe, by saving info in a database.
I have two tables, Games(ID,Winner) and Turns(ID,Turn,GameID,Place,Shape).
I want to find parent by multiple child infos.
For Example:
SELECT GameID FROM Turns WHERE
GameID IN (WHEN Turn = 1 THEN Place = 1) AND GameID IN (WHEN Turn = 2 THEN Place = 4);
Is something like this possible?
Im using ms-access.
Turm - Game turn GameID - Game ID Place - Place on matrix
1=top right, 9=bottom left Shape - X or circle
Thanks in advance
This very simple query will do the trick in a single scan, and doesn't require you to violate First Normal Form by storing multiple values in a string (shudder).
SELECT T.GameID
FROM Turns AS T
WHERE
(T.Turn = 1 AND T.Place = 1)
OR (T.Turn = 2 AND T.Place = 4)
GROUP BY T.GameID
HAVING Count(*) = 2;
There is no need to join to determine this information, as is suggested by other answers.
Please use proper database design principles in your database, and don't violate First Normal Form by storing multiple values together in a single string!
The general solution to your problem can be accomplished by using a sub-query that contains a self-join between two instances of the Turns table:
SELECT * FROM Games
WHERE GameID IN
(
SELECT Turns1.GameID
FROM Turns AS Turns1
INNER JOIN Turns AS Turns2
ON Turns1.GameID = Turns2.GameID
WHERE (
(Turns1.Turn=1 AND Turns1.Place = 1)
AND
(Turns2.Turn=2 AND Turns2.Place = 4))
);
The Self Join between Turns (aliased Turns1 and Turns2) is key, because if you just try to apply both sets of conditions at once like this:
WHERE (
(Turns.Turn=1 AND Turns.Place = 1)
AND
(Turns.Turn=2 AND Turns.Place = 4))
you will never get any rows back. This is because in your table there is no way for an individual row to satisfy both conditions at the same time.
My experience using Access is that to do a complex query like this you have to use the SQL View and type the query in on your own, rather than use the Query Designer. It may be possible to do in the Designer, but it's always been far easier for me to write the code myself.
select GameID from Games g where exists (select * from turns t where
t.gameid = g.gameId and ((turn =1 and place = 1) or (turn =2 and place =5)))
This will select all the games that have atleast one turn with the coresponding criteria.
More info on exist:
http://www.techonthenet.com/sql/exists.php
I bypassed this problem by adding a column which holds the turns as a string example : "154728" and i search for it instead. I think this solution is also less demanding on the database

LLblgen: Select distinct?

I can't seem to figure out how I can select only distinct entries in Llblgen 2.6 self-service model
I essentially want this query.
select distinct City
from peopleTable
where *predicates*
I've got my PeopleCollection and I'm not sure if there's a distinct method I can call or argument I can pass to GetMulti().
Entities by definition cannot be distinct - even if they have the same value they are different rows in the same table.
You could use a TypedList or DynamicList to get a distinct list of city values - one of the parameters on the Fetch call is to get distinct items.
Or if you are using LINQ you could do
List<string> cities = PeopleCollection.Select(x=>x.City).Distinct();
Adding a diff't answer to compliment Matt's, since I ended up here, but couldn't find a simple answer of how to do this anywhere, and you can't format code in a comment
ResultsetFields fields = new ResultsetFields(1);
fields.DefineField(PeopleFields.City, 0);
DataTable dynamicList = new DataTable();
adapter.FetchTypedList(fields, dynamicList, null, false);
foreach (DataRow row in dynamicList.Rows)
Cities.Add(row[0] as string);
This gives a distinct list of all cities, filtering is done with an IRelationPredicateBucket instead of null to FetchTypedList.

Django annotate() multiple times causes wrong answers

Django has the great new annotate() function for querysets. However I can't get it to work properly for multiple annotations in a single queryset.
For example,
tour_list = Tour.objects.all().annotate( Count('tourcomment') ).annotate( Count('history') )
A tour can contain multiple tourcomment and history entries. I'm trying to get how many comments and history entries exist for this tour. The resulting
history__count and tourcomment__count
values will be incorrect. If there's only one annotate() call the value will be correct.
There seems to be some kind of multiplicative effect coming from the two LEFT OUTER JOINs. For example, if a tour has 3 histories and 3 comments, 9 will be the count value for both. 12 histories + 1 comment = 12 for both values. 1 history + 0 comment = 1 history, 0 comments (this one happens to return the correct values).
The resulting SQL call is:
SELECT `testapp_tour`.`id`, `testapp_tour`.`operator_id`, `testapp_tour`.`name`, `testapp_tour`.`region_id`, `testapp_tour`.`description`, `testapp_tour`.`net_price`, `testapp_tour`.`sales_price`, `testapp_tour`.`enabled`, `testapp_tour`.`num_views`, `testapp_tour`.`create_date`, `testapp_tour`.`modify_date`, `testapp_tour`.`image1`, `testapp_tour`.`image2`, `testapp_tour`.`image3`, `testapp_tour`.`image4`, `testapp_tour`.`notes`, `testapp_tour`.`pickup_time`, `testapp_tour`.`dropoff_time`, COUNT(`testapp_tourcomment`.`id`) AS `tourcomment__count`, COUNT(`testapp_history`.`id`) AS `history__count`
FROM `testapp_tour` LEFT OUTER JOIN `testapp_tourcomment` ON (`testapp_tour`.`id` = `testapp_tourcomment`.`tour_id`) LEFT OUTER JOIN `testapp_history` ON (`testapp_tour`.`id` = `testapp_history`.`tour_id`)
GROUP BY `testapp_tour`.`id`
ORDER BY `testapp_tour`.`name` ASC
I have tried combining the results from two querysets that contain a single call to annotate (), but it doesn't work right... You can't really guarantee that the order will be the same. and it seems overly complicated and messy so I've been looking for something better...
tour_list = Tour.objects.all().filter(operator__user__exact = request.user ).filter(enabled__exact = True).annotate( Count('tourcomment') )
tour_list_historycount = Tour.objects.all().filter( enabled__exact = True ).annotate( Count('history') )
for i,o in enumerate(tour_list):
o.history__count = tour_list_historycount[i].history__count
Thanks for any help. Stackoverflow has saved my butt in the past with a lot of already-answered questions, but I wasn't able to find an answer to this one yet.
Thanks for your comment. That didn't quite work but it steered me in the right direction. I was finally able to solve this by adding distinct to both Count() calls:
Count('tourcomment', distinct=True)
tour_list = Tour.objects.all().annotate(tour_count=Count('tourcomment',distinct=True) ).annotate(history_count=Count('history',distinct=True) )
You have to add distinct=True to get the proper result else it will return the wrong answer.
I can't guarantee that this will solve your problem, but try appending .order_by() to your call. That is:
tour_list = Tour.objects.all().annotate(Count('tourcomment')).annotate(Count('history')).order_by()
The reason for this is that django needs to select all the fields in the ORDER BY clause, which causes otherwise identical results to be selected. By appending .order_by(), you're removing the ORDER BY clause altogether, which prevents this from happening. See the aggregation documentation for more information on this issue.