MyBatis Data Mapping. Collection. Relational Tables - mysql

fund_allocation_template
template_id | template_name | status |
1 Mega Lotto 1
2 EZ-2 1
fund_allocation_item
| item_id | item_name | status |
1 Charity 1
2 Operation Expenses 1
3 Food Allowance 1
4 Transportation Allowance 1
| 5 | Calamity Victims | 1 |
r_template_item
| template_id | item_id | item_percentage |
1 1 45.00
1 2 55.00
2 1 40.00
2 2 46.00
//FundAllocationTemplate.java(domain)
private Integer templateID;
private String templateName;
private Integer templateStatus
//FundAllocationItem.java(domain)
private Integer itemID;
private String itemName;
private Integer itemStatus
<resultMap id="fundTemplate" type="FundAllocationTemplate">
<id property="fundTemplateID" column="template_id" />
<result property="fundTemplateName" column="template_name" />
<result property="fundTemplateStatus" column="status" />
//Association for Status
</resultMap>
<resultMap id="fundItem" type="FundAllocationItem">
<id property="fundItemID" column="item_id" />
<result property="fundItemName" column="item_name" />
<result property="fundItemStatus" column="status" />
//Association for Status
</resultMap>
FORM
private Integer templateID;
private String templateName;
private BigDecimal totalPercentage;
private Integer status;
Form Or Page Output
| Allocation Template Name | Fund Template Percentage | Status |
| Mega Lotto | 100% | Active |
| EZ-2 | 86% | Active |
Question: How can I be able to show the total percentage of every Fund Template with the given domain and table design?

Use the following query:
select T.template_name,SUM(R.item_percentage) as Fund_Template_Percentage,
(CASE T.status WHEN 1 THEN "Active" ELSE "NOT Active" END) STATUS
from fund_allocation_template T, r_template_item R
where T.template_id=R.template_id
GROUP BY R.template_id;

Related

MYSQL sorting with doctrine

as described in this question and as its answered with "Not possible"
i opened a new question
so my problem goes like this :
I have a table (ServiceProvider Table)
each service provider have many offers (Offer table) with a OneToMany relation
and each Offer have a master service (Service table) with a ManyToOne relation.
What i am trying to do is to get all the service providers and their offers in an order related to serviceProvider.points and then serviceProvider.name and each service provider's offers should be ordered by their points.
So for more clear view let's say i have the following
ServiceProvider
-------------------------------------------------
id | name | points |offers|
-------------------------------------------------
1 | c | 2 |1,2,3 |
-------------------------------------------------
2 | b | 1 |1,2 |
-------------------------------------------------
3 | a | 0 |1,3 |
-------------------------------------------------
ServiceOffer
-----------------------------------
id | name |service|
-----------------------------------
1 | a | 1 |
-----------------------------------
2 | b | 1 |
-----------------------------------
3 | c | 2 |
-----------------------------------
Service
-----------------------------------
id | name | points |
-----------------------------------
1 | a | 23 |
-----------------------------------
2 | b | 88 |
-----------------------------------
what i exactly need is a result like this
results
service_provider.name| offers.name |
-------------------------------------
c | b , a |
-------------------------------------
b | a , b |
-------------------------------------
a | b , a |
-------------------------------------
this is the query i tried but it's not working
$query->select("sp")
->from("CoreBundle:ServiceProvider","sp")
->andWhere("sp.city = :city_name")->setParameter("city_name",$cityName)
->innerJoin("sp.offers","offer")
->innerJoin("offer.service","service","with","offer.service = service")
->orderBy("sp.points DESC , sp.name ASC , service.points");
needed fields
in serviceProvider
/**
* #var ServiceOffer
*
* #ORM\OneToMany(targetEntity="ServiceOffer", mappedBy="serviceProvider")
*/
private $offers;
in service
/**
* #var integer
*
* #ORM\Column(name="points", type="integer", nullable=true)
*/
private $points;
in service offer
/**
* #ORM\ManyToOne(targetEntity="Service", inversedBy="offer")
* #ORM\JoinColumn(name="service_id", referencedColumnName="id")
*
* #Serializer\Expose
* #Serializer\Groups({"service-offer", "order-entry"})
*
* #Assert\NotBlank(message="constraint.serviceOffer.service.not_blank")
*/
private $service;
You cannot simply enumerate ORDER BY directives to Doctrine. You may give a single ->orderBy() method call, giving the field to use and direction (optional, ASC is default) as arguments, and further order fields must be add using the addOrderBy method. Your query should look like
$query->select("sp")
->from("CoreBundle:ServiceProvider","sp")
->andWhere("sp.city = :city_name")->setParameter("city_name",$cityName)
->innerJoin("sp.offers","offer")
->innerJoin("offer.service","service","with","offer.service = service")
->orderBy("sp.points", "DESC")
->addOrderBy("sp.name", "ASC")
->addOrderBy("service.points");
See the documentation on this topic.
The #SolarBear 's answer is almost correct.
$query->select("sp, offer, service")
->from("CoreBundle:ServiceProvider","sp")
->andWhere("sp.city = :city_name")->setParameter("city_name",$cityName)
->innerJoin("sp.offers","offer")
->innerJoin("offer.service","service")
->orderBy("sp.points", "DESC")
->addOrderBy("sp.name", "ASC")
->addOrderBy("service.points","DESC");
Notice, I remove the unnecessary code in the service Inner Join. And more important, add 'DESC' string in service.points order by. It should do the trick.
Let's jump to your example :
First of all, I honestly didn't understand you map in column ServiceProvider.offers. Second, I change names of these table to be more clear to show the expected result.
ServiceProvider
-------------------------------------------------
id | name | points |offers|
-------------------------------------------------
1 | C | 2 |1,2,3 |
-------------------------------------------------
2 | B | 1 |1,2 |
-------------------------------------------------
3 | A | 0 |1,3 |
-------------------------------------------------
ServiceOffer
-----------------------------------
id | name |service|
-----------------------------------
1 | Z | 1 |
-----------------------------------
2 | Y | 1 |
-----------------------------------
3 | X | 2 |
-----------------------------------
Service
-----------------------------------
id | name | points |
-----------------------------------
1 | J | 23 |
-----------------------------------
2 | K | 88 |
-----------------------------------
results
ServiceProvider.name | offers.name |
---------------------------------------------
C | X, Y, Z or X, Z, Y | <---- I explain below
---------------------------------------------
B | Y, Z or Z, Y | <---- Same
---------------------------------------------
A | X, Z |
---------------------------------------------
In this example, SeviceOffer X uses Service K (points 88). While, ServiceOffer Y and Z use Service J (points 23) so there is a draw between the ServiceProvider Y and Z, so the DB can returns they in any order.
Edit
About "offers" column. Notice you mapped as a One to Many relationship. But notice, in the given table example is sound like a Many to Many. Once, ServiceProvider has many ServiceOffer and vice-versa. So for this works properly you should create a join table and removing offers column.
And map in ServiceProvider a ManyToMany relationship.
Such as:
Providers_Offers
------------------------------
provider_id | offer_id |
------------------------------
1 | 1 |
------------------------------
1 | 2 |
------------------------------
1 | 3 |
------------------------------
2 | 1 |
------------------------------
2 | 2 |
------------------------------
3 | 1 |
------------------------------
3 | 3 |

how to select union of two columns of same table in hql

I need to retrieve all the account numbers of the transaction table/object which given below. Using mysql for database.
Entity Class
public class Transaction implements java.io.Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#Column(name = "cr_account_ref")
private String crAccountRef;
#Column(name = "dr_account_ref")
private String drAccountRef;
#Column(name = "amount")
private String amount;
// getters and setters.
}
My Table
| cr_account_ref | dr_account_ref | amount |
|----------------------------------------------------------
|1000001 |2000009 | 100 |
|1000002 |2000008 | 500 |
|1000001 |2000006 | 100 |
|1000003 |2000004 | 500 |
|1000005 |2000008 | 611 |
|1000001 |2000009 | 300 |
|1000002 |2000004 | 120 |
-----------------------------------------------------------
What i need is, distinct of all the account numbers(both debit and credit.).
| cr_account_ref |
|----------------------
|1000001 |
|1000002 |
|1000003 |
|1000005 |
|2000004 |
|2000006 |
|2000008 |
|2000009 |
-----------------------
This is easy with pure jdbc, but i need to do the this with HQL.

MySQL: GROUP BY with custom hierarchical functionality

I've got a permission/privileges - table looking like this:
+----+----------+----------+------+-------+
| id | name | usertype | read | write |
+----+----------+----------+------+-------+
| 1 | test | A | 0 | 0 |
| 2 | test | MU | 1 | 1 |
| 3 | test | U | 1 | 1 |
| 4 | apple | A | 1 | 1 |
| 5 | apple | MU | 1 | 0 |
| 6 | apple | U | 0 | 0 |
| 7 | flower | A | 0 | 0 |
| 8 | flower | MU | 0 | 0 |
| 9 | flower | U | 1 | 1 |
+----+----------+----------+------+-------+
there are 3 usertypes: A (admin), MU (maintenance user), U (standard user)
the usertypes are hierarchical: A > MU > U
(the usertypes are saved as CHAR(2) in the database, and unfortunately I can't change that)
now i want to build a query which implements the hierarchical logic of my usertypes.
e.g. usertype 'A' got no permission to read or write on stuff with the name 'test', thus usertypes 'MU' AND 'U' also should have no permission for that and their read = 1 and write = 1 should be ignored.
I know which usertype is currently logged in.
I somehow have to check for the minimum of read/write rights to the name for all hierarchical predecessors, i guess. but i don't know how to check that since usertype is not a number field.
this is what I've tried so far:
SELECT
name,
MIN(read),
MIN(write),
CASE
WHEN usertype = 'A' THEN 0
ELSE (CASE
WHEN usertype = 'WU' THEN 1
ELSE 2
END)
END userval
FROM
permissions
-- WHERE usertype <= :current_usertype
GROUP BY name
this seems to work, but i don't know how i can get my condition WHERE usertype <= :current_usertype working, so a usertype down in the hierarchy can't get more privileges on a name than a "higher" usertype.
any ideas?
thanks in advance!
This is how I solved my problem:
1. I added another table "permission_groups" to the database:
+----+----------+--------+
| id | usertype | value |
+----+----------+--------+
| 1 | A | 100 |
| 2 | MU | 20 |
| 3 | U | 10 |
+----+----------+--------+
2. Then I joined this table to my original table "permissions" which i showed in my question:
here i get the value of my "permission_groups" table with a subquery. this value symbolizes the hierarchical order of my different usertypes.
SELECT
perm.name,
MIN(perm.`read`),
MIN(perm.`write`),
group .value
FROM
permissions perm
LEFT JOIN permission_groups group ON group.usertype = perm.usertype
WHERE
group.value >= (SELECT value from permission_groups WHERE usertype = :current_usertype)
GROUP BY perm.name
:current_usertype is a PDO parameter in my case, which is replaced by the usertype of the current user.

Ebean ManyToMany: Model A has ManyToMany<Model B> . select count(*) B where B in A's List<B>

The application allows users to select certain keywords (which we monitor the TwitterStream for)
Each Keyword contains a list of the tweet IDs that contain its keyword.
public class Keyword extends Model {
#Id
int id;
String keyword;
#ManyToMany
public List<Tweet> tweets = new ArrayList();
}
public class Tweet extends Model {
#Id
int id;
TimeStamp datetime;
}
I'd like to get some data on how each keyword performs each day by select count(*), datetime grouping them by day. The following SQL query will accomplish what I need.
select datetime, count(*) from tweet t left outer join keyword_tweet on t.id=keyword_tweet.tweet_id group by cast(t.datetime as date) having t.datetime > '2014-02-02';
+---------------------+----------+
| datetime | count(*) |
+---------------------+----------+
| 2014-02-02 13:27:45 | 1 |
| 2014-02-08 05:14:04 | 2 |
| 2014-02-09 08:34:31 | 1 |
| 2014-02-12 12:42:02 | 1 |
| 2014-02-13 06:00:09 | 2 |
| 2014-02-14 00:47:04 | 2 |
| 2014-02-15 07:26:30 | 6 |
| 2014-02-16 01:00:00 | 21 |
| 2014-02-17 00:06:50 | 916 |
| 2014-02-18 18:08:56 | 1 |
| 2014-02-19 01:28:40 | 1 |
| 2014-02-24 16:45:11 | 1 |
| 2014-02-26 14:43:54 | 4 |
| 2014-02-27 08:24:09 | 9 |
| 2014-02-28 05:08:16 | 411 |
+---------------------+----------+
How do I select * from Tweets where Tweet.id is IN Keyword.tweets ?
Also how in Ebean would I get a List that only contains Dates, and Count(*)?
Thanks guys!
You can use something along these lines:
Keyword targetKeyword = Keyword.find.byId(1L);
List<Tweets> foundTweets = new ArrayList<Tweets>();
for(Tweet tw : Tweets.find.all()) {
if(targetKeyword.tweets.contains(tw))
foundTweets.add(tw);
}
return foundTweets;
This code will return all tweets contained in keyword id number 1. You can place this in a function passing the keyword id you want instead of 1L.

MySQL Retrieve Records Where Criteria is Unique and True i.e. No other records exist

I have a legacy database that I am working with a basic column layout as such:
SampleID
CompanyID
CompanyApplication
CompanyTest1
...
CompanyTest25
Not normalized in the least, this is causing a bit of a data mining issue.
I need to get the CompanyIDs (Grouped By) where the CompanyApplication field = "Registration" but this company has none of the CompanyTest(n) fields selected for any SampleID.
The problem is, there are CompanyIDs that have both CompanyApplication and CompanyTest(n) records (multiple rows), but I want to get CompanyIDs that only have a CompanyApplication of Registration.
Data to help illustrate:
SampleID | CompanyID | CompanyApplication | CompanyTest1 | ... | CompanyTest25
------------------------------------------------------------------------
1 | 1 | Registration | | |
------------------------------------------------------------------------
2 | 1 | | True | |
------------------------------------------------------------------------
3 | 2 | Registration | | |
------------------------------------------------------------------------
4 | 2 | Registration | | |
------------------------------------------------------------------------
5 | 3 | | True | |
------------------------------------------------------------------------
6 | 3 | | | | True
I only want to retrieve rows 3 and 4 because they ONLY have Registration and no other testing.
We could start by selecting all of the rows that you are trying to exclude, and then use a NOT EXISTS to skip over CompanyIDs that are in that query.
SELECT DISTINCT ct1.company_id
FROM company_table AS ct1
WHERE ct1.CompanyApplication = "Registration"
AND NOT EXISTS(
SELECT 1
FROM company_table AS ct2
WHERE ct1.company_id = ct2.compnay_id
AND (ct2.CompanyTest1 IS NOT NULL
OR ct2.CompanyTest2 IS NOT NULL
...
OR ct2.CompanyTest25 IS NOT NULL)
)