In Grails... How to union two tables in a single controller? - database

I have two tables, but they are installed as plugin in Grails.
Columns in T1 are: a1, b1, c1, d1
Columns in T2 are: a2, b2, c2, d2
I need to select columns a*, b*, c*, d* (=1,2) from both tables in a controller as union and sort all of them by the column d, how can I do that?
Furthermore, how can the pagination work as treating about result as a single table?
Pls help. Appreciate!!

Not sure if this is helpful or not. We hit a similar (though not exact) problem in the past, and we solved it by creating a view. You can create the view to do your union and select, and then create the new domain class that maps to the view.
You won't be able to use grails auto create for the table, which is another limitation.

On pagination:
groovy.sql.Sql rows() and eachRow() have 2nd and 3rd parameters max and offset that you can paginate with all like in ordinary list.
Retrieve total count with another SQL query or some other way. Construct a PagedResultList from a data page rows() and int totalCount - and you got an object that you can use as a model.

Related

Groupby and count() with alias and 'normal' dataframe: python pandas versus mssql

Coming from a SQL environment, I am learning some things in Python Pandas. I have a question regarding grouping and aggregates.
Say I group a dataset by Age Category and count the different categories. In MSSQL I would write this:
SELECT AgeCategory, COUNT(*) AS Cnt
FROM TableA
GROUP BY AgeCategory
ORDER BY 1
The result set is a 'normal' table with two columns, the second column I named Count.
When I want to do the equivalent in Pandas, the groupby object is different in format. So now I have to reset the index and rename the column in a following line. My code would look like this:
grouped = df.groupby('AgeCategory')['ColA'].count().reset_index()
grouped.columns = ['AgeCategory', 'Count']
grouped
My question is if this can be accomplished in one go. Seems like I am over-doing it, but I lack experience.
Thanks for any advise.
Regards, M.
Use parameter name in DataFrame.reset_index:
grouped = df.groupby('AgeCategory')['ColA'].count().reset_index(name='Count')
Or:
grouped = df.groupby('AgeCategory').size().reset_index(name='Count')
Difference is GroupBy.count exclude missing values, GroupBy.size not.
More information about aggregation in pandas.

Count BelongToMany relationship in CakePHP 3.2

I have a Table A related many to many with a Table B and I want to know how many related rows I have in B with a given A entity.
In SQL it would be something like this:
SELECT COUNT(*) FROM AB WHERE A_id=1;
I thought that I should place it in the model of A with a Virtual Field that retrieves the count, but I didnĀ“t find a way to use the model itself to get the related B rows.
I tried with
$this->contain(['B'])->count()
But it didn't work because 'contain' is undefined. So, how should I get the count?
Make sure that u put the association in both of your models initialize method and dont call contain() on $this.
$query = $this->A->find();
numberOfRecords = $query->contain(['B'])->count;

Array intersect Hive

I have two arrays of string in Hive like
{'value1','value2','value3'}
{'value1', 'value2'}
I want to merge arrays without duplicates, result:
{'value1','value2','value3'}
How I can do it in hive?
A native solution could be that:
SELECT id, collect_set(item)
FROM table
LATERAL VIEW explode(list) lTable AS item
GROUP BY id;
Firstly explode with lateralview, and next group by and remove duplicates with collect_set.
You will need a UDF for this. Klout has a bunch of opensource HivUDFS under the package
brickhouse. Here is the github link. They have a bunch of UDF's that exactly serves your purpose.
Download,build and add the JAR. Here is an example
CREATE TEMPORARY FUNCTION combine AS 'brickhouse.udf.collect.CombineUDF';
CREATE TEMPORARY FUNCTION combine_unique AS 'brickhouse.udf.collect.CombineUniqueUDAF';
select combine_unique(combine(array('a','b','c'), array('b','c','d'))) from reqtable;
OK
["d","b","c","a"]

How to sort a Doctrine DQL Query by the number or members of a relation?

I'm trying to create a query for retrieving objects from a Doctrine database, sorted by the number of members of a specific one-to-many relationship.
More specifically: I have two Entities: Person and Federation. A person can be a member of one federation (Person has 'federation' relationship), and a federation may have n people (Federation as 'people' relationship).
I would like to create a DQL Query that would return the list of Federations, ordered by how many people are members of that Federation. Something along these lines:
SELECT f FROM AcmeStatsBundle:Federation f ORDER BY [number of members of f.people]
That would be the first step. There is an additional second step, which I don't know if is possible to achieve with a single query, which would be filtering the members of the relation prior the counting. Like so:
SELECT f FROM AcmeStatsBundle:Federation f ORDER BY [number of (f.people p where p.attr = value)]
That second one would be the optimal result, but the first one satisfies my needs, if the second case is not feasibly in a single query.
Thanks in advance.
You could do something along the lines of:
public function getFederationsOrderedByNumberOfPeople()
{
return $this->createQueryBuilder('f')
->addSelect('COUNT(p) AS HIDDEN personCount');
->leftJoin('f.people', 'p');
->groupBy('f')
->orderBy('personCount', 'DESC');
}
The HIDDEN keyword was added in Doctrine 2.2, it means that the selected field won't be in the results, and in this case that means you just get your entities back instead of an array.
Reference to DQL SELECT documentation: http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html#dql-select-examples
There are 5 aggregate functions in DQL you can use (Doctrine 2.2): AVG, COUNT, MIN, MAX and SUM.
The following query should work:
SELECT f
FROM AcmeStatsBundle:Federation f
LEFT JOIN f.people p
GROUP BY f.id
ORDER BY COUNT(p)
WHERE p.attr = :some_value
For more DQL trickery I suggest you look up official Doctrine docs.

Equivalent of "IN" that uses AND instead of OR logic?

I know I'm breaking some rules here with dynamic SQL but I still need to ask. I've inherited a table that contains a series of tags for each ticket that I need to pull records from.
Simple example... I have an array that contains "'Apples','Oranges','Grapes'" and I am trying to retrieve all records that contain ALL items contained within the array.
My SQL looks like this:
SELECT * FROM table WHERE basket IN ( " + fruitArray + " )
Which of course would be the equivalent of:
SELECT * FROM table WHERE basket = 'Apples' OR basket = 'Oranges' OR basket = 'Grapes'
I'm curious if there is a function that works the same as IN ( array ) except that it uses AND instead of OR so that I can obtain the same results as:
SELECT * FROM table WHERE basket LIKE '%Apples%' AND basket LIKE '%Oranges%' AND basket LIKE '%Grapes%'
I could probably just generate the entire string manually, but would like a more elegant solution if at all possible. Any help would be appreciated.
This is a very common problem in SQL. There are basically two solutions:
Match all rows in your list, group by a column that has a common value on all those rows, and make sure the count of distinct values in the group is the number of elements in your array.
SELECT basket_id FROM baskets
WHERE basket IN ('Apples','Oranges','Grapes')
GROUP BY basket_id
HAVING COUNT(DISTINCT basket) = 3
Do a self-join for each distinct value in your array; only then you can compare values from multiple rows in one WHERE expression.
SELECT b1.basket_id
FROM baskets b1
INNER JOIN baskets b2 USING (basket_id)
INNER JOIN baskets b3 USING (basket_id)
WHERE (b1.basket, b2.basket, b3.basket) = ('Apples','Oranges','Grapes')
There may be something like that in full text search, but in general, I sincerely doubt such an operator would be very useful, outside the conjunction with LIKE.
Consider:
SELECT * FROM table WHERE basket ='Apples' AND basket = 'Oranges'
it would always match zero rows.
If basket is a string, like your example suggests, then the closest you could get would be to use LIKE '%apples%oranges%grapes%', which could be built easily with '%'.implode('%', $tags).'%'
The issue with this is if some of 'tags' might be contained in other tags, e.g. 'supercalifragilisticexpialidocious' LIKE '%super%' will be true.
If you need to do LIKE comparisons, I think you're out of luck. If you are doing exact comparisons invovling matching sets in arbitrary order, you should look into the INTERSECT and EXCEPT options of the SELECT statement. They're a bit confusing, but can be quite powerful. (You'd have to parse your delimited strings into tabular format, but of course you're doing that anyway, aren't you?)
Are the items you're searching for always in the same order within the basket? If yes, a single LIKE should suffice:
SELECT * FROM table WHERE basket LIKE '%Apples%Oranges%Grapes%';
And concatenating your array into a string with % separators should be trivial.

Resources