Find the count of elements from another table - mysql

First the schema - i have 4 tables:
office - officeid, officename
member - memberid, officeid, membername (multiple members per office)
transaction - transactionid, memberid, transactiontype (multiple transactions per member)
activity - activityid, officeid (multiple activities per office)
How can i get the list of member names, along with offices and the count of each transaction type and total count of activities for that office with a single query?
I have tried myself and i can get the office names, member names and activity count but not able to get the transaction count (per transaction type) with a single query. Wondering if this is possible at all.
Any suggestions/help is appreciated. Please let me know if i can provide any details which i missed
Edit - I added a sqlfiddle with some sample data at http://sqlfiddle.com/#!9/9cf7b/1
Also realized i had missed the officeid foreign key in the member table.
Edit - Adding expected output
officename, membername, transaction_count_1, trasaction_count_2, activitycount
abc , aa , 1 , 1, , 3
abc , bb , 1 , 0, , 1
abc , cc , 0 , 1, , 0

I think this can solve your purpose.
select b.membername,a.officename,count(transactiontype)
from office a,
member b,
transaction c
where a.officeid = b.officeid
and b.memberid = c.memberid
group by b.membername,a.officename
If you need any further data manipulation just give me an idea (perferably a screenshot or an image) of how your output shall look and i shall change the query accordingly.
Thanks.

Related

Need to retrieve the most recent room type/Rateplan combination (mysql)

I will explain the logic:
I need to retrieve only the most recent room type/rate plan combinations from the rateplan_roomtypeTable.
room type ID and rate plan id are located in separate columns
there are 2 conditions that need to be met: all active room type/rate plan combinations need to be retrieved along with all room type/rate plan combinations that have produced even if they are not active. All these combinations need to be the most recent ones.
The desired results would be like the table I ll share with you:
Your help with the below query will be much appreciated:
select
Id
, RoomTypeId
, RateTypeId
,isactiveRateType
,isactiveRoomType
, RatePlanName
, RoomTypeName
FROM
rateplan_roomtypeTable
where
RateTypeId IN (select RateTypeId from ProductionTable where (cast(bookingdate as date) between date_add('day',-92, current_date) and date_add('day', -2, current_date)))
OR (isactiveRateType = 1 and isactiveRoomType = 1)
GROUP BY
1,2,3,4,5
Thank you

I want to use a group by for a nvarchar data type

My goal is to create a query that can group by 3 respective survey types and their respective values. the columns are The date is automatically updated every couple of days, the Survey type broken down into different survey types being survey a , survey b and survey c. These surveys can be either labeled sent (meaning the customer is in possession and has not completed it) or it can be labeled received(meaning the customer has completed it and the information is received.Each of the survey strings begin with the same 4 characters XXX- . This is where my use of wildcard % comes into play. the format of the survey type is XXX-YY-SENT or "XXX-YY-RECIEVED" .The YY are distinct to the specific survey type. The value column gives the total number of surveys completed by the date which is updated by the system every 2 weeks. My goal is to group the data by its survey type in order to be able to create a stacked column chart in ssrs showing the difference between sent and received surveys. (which I already have a good idea on how to execute. The issue is developing the query in order to pull the data and group it by Survey X (Group being survey x-SENT and survey x-recieved) and Survey Y (Group being survey y-SENT and survey y-recieved) and Survey Z (Group being survey z-SENT and survey z-recieved).here is example data from table SurveyInfo. This is the query i use to pull my data:
SELECT [Date] ,[SurveyType] ,[Value]
FROM SurveyInfo]
WHERE Date IN (SELECT max(Date) FROM SurveyInfo) and SurveyType like '%XXX%'
(this is where i would like to group the data by survey type)
this is the data result.
Date , SurveyType, Value
2017-06-02 08:00:02.270 XXX-AA-SENT-WITHIN-2YR 1000.0000
2017-06-02 08:00:02.270 XXX-AA-RECEIVED-WITHIN-2YR 900.0000
2017-06-02 08:00:02.270 XXX-BB-SENT-WITHIN-2YR 1200.0000
2017-06-02 08:00:02.270 XXX-BB-RECEIVED-2YR 800.0000
2017-06-02 08:00:02.270 XXX-CC-SENT-WITHIN-2YR 500.0000
2017-06-02 08:00:02.270 XXX-CC-RECEIVED-WITHIN-2YR 400.0000
That was hard to read through but I think I understand what you want. Does the below start to help you out?
if object_id('tempdb.dbo.#test') is not null drop table #test
create table #test
(
dateVal datetime,
SurveyType nvarchar(500),
SurveyValue decimal(36,4)
)
insert into #test
values('2017-06-02 08:00:02.270','XXX-AA-SENT-WITHIN-2YR',1000.0000),
('2017-06-02 08:00:02.270','XXX-AA-RECEIVED-WITHIN-2YR', 900.0000),
('2017-06-02 08:00:02.270','XXX-BB-SENT-WITHIN-2YR', 1200.0000),
('2017-06-02 08:00:02.270','XXX-BB-RECEIVED-2YR', 800.0000),
('2017-06-02 08:00:02.270','XXX-CC-SENT-WITHIN-2YR', 500.0000),
('2017-06-02 08:00:02.270','XXX-CC-RECEIVED-WITHIN-2YR', 400.0000)
SELECT
substring(SurveyType,5,2) as SurveyType,
case when SurveyType like '%SENT%' then 'SENT' else 'RECEIVED' END as SENT_RECEIVED,
sum(SurveyValue) as SumSurveyValue
FROM #test
GROUP BY
substring(SurveyType,5,2) ,
case when SurveyType like '%SENT%' then 'SENT' else 'RECEIVED' END
ORDER BY
SurveyType,
SENT_RECEIVED

Concatenate references of duplicate values in MySQL

I have a table (chapter) that contains 5 columns for officers in an organization: ID (key), president, vice_president, secretary, treasurer. For each office there is the value of a reference number to an individual.
For some IDs, the same value is listed for more than one of the 4 offices. You can see a basic example of my data structure below:
ID president vice_president secretary treasurer
105 1051456 1051456 1051466 1051460
106 1060923 1060937 1060944 1060944
108 1081030 1081027 1081032 1081017
110 1100498 1100491 1100485 1100485
I have also posted the same at http://sqlfiddle.com/#!9/57df1
My goal is to identify when a value is in more than one field and to SELECT that value as well as a concatenated list of all of the column titles in which it is found. For example from the supplied sample dataset, I would ideally like to return the following:
member offices
1051456 president, vice_president
1060944 secretary, treasurer
1100485 secretary, treasurer
I have found a few other examples that are similar, but nothing seems work towards what I am looking to do. I'm a novice but can piece things together from examples fairly well. I was also thinking that there might be an easier way by joining with the information_schema database as that is how I have pulled column titles in the past. It doesn't seem that this should as difficult as it is, and hopefully I am missing an easy and obvious solution. My full dataset is rather large and I would prefer to avoid any intensive sub-queries for the sake of performance. My SQL format is MySQL 5.5.
Any help or guidance would be greatly appreciated!
One method uses union all to unpivot the data and then re-aggregates:
select member, group_concat(office)
from ((select id, president as member, 'president' as office from t) union all
(select id, vice_president, 'vice_president' as office from t) union all
(select id, secretary, 'secretary' as office from t) union all
(select id, treasurer, 'treasurer' as office from t)
) t
group by member
having count(distinct office) > 1;
If you want to control the order of the values, then add a priority:
select member, group_concat(office order by priority) as offices
from ((select id, president as member, 'president' as office, 1 as priority from t) union all
(select id, vice_president, 'vice_president' as office, 2 from t) union all
(select id, secretary, 'secretary' as office, 3 from t) union all
(select id, treasurer, 'treasurer' as office, 4 from t)
) t
group by member
having count(distinct office) > 1;

Select a row based on the value of another row

App goal
Send messages from retailers to registered customers mobile via GCM
DB architecture
I have a customers table and a related customers_realtions table with the following fields: id, customerID, retailerID, isBlocked
Required outcome
A customer can register for a specific retailer, or for a wildcard (all of them).
In case one registers for all the retailers, he has an option to block a specific retailer from sending future messages, effectively creating a blacklist.
DB values for each status
When a customer registers for a single retailer retailerID is assigned with the retailer ID.
When a customer register for all of the retailers retailerID equals 1.
When a customer blocks a retailer there are two options:
a. if he registered to this specific retailer before the isBlocked field is updated to 1 (true)
b. if he registered to all retailers before a new row is created for this retailer and isBlocked is set to 1 (true)
The challenge
When sending the message the SELECT query should include the customers that has a retailerID of 1 and does not have the sending retailerID when isBlocked equals 1.
For example, in this situation
id customerID retailID isBlocked
129 46 111 1
128 46 1 0
I don't want the customer to be selected even if the retailerID is 111
My attempt
SELECT * FROM customers_relations
WHERE
(retailID=111
OR
(retailID=1
AND
(SELECT isBlocked FROM `customers_relations` WHERE customerID=46 AND retailID=111)=0))
AND
NOT isBlocked
Question
While this is working for a single customer for whom I know the ID in advance, I am struggling to figure a way of writing a similar query for multiple customers.
I think of this as an aggregation query. You want to look through all the rows that are not blocked for a customer and determine whether retailer 111 is available or all retailers are available:
SELECT customerId
FROM customers_relations cr
WHERE isBlocked = false
GROUP BY customerId
HAVING MAX(retailId = 111) > 0 OR
MAX(retailId = 1) > 0;
I notice that your question actually says that a new row is created in customer_relations when someone is blocked. The above assumes there is one row. To handle the case when a block on any row would cause a block, then:
SELECT customerId
FROM customers_relations cr
GROUP BY customerId
HAVING (MAX(retailId = 111) > 0 OR
MAX(retailId = 1) > 0
) AND
MAX(retailId = 111 AND isblocked = true) = 0;

Excluding 'near' duplicates from a mysql query

We have an iPhone app that sends invoice data by each of our employees several times per day. When they are in low cell signal areas tickets can come in as duplicates, however they are assigned a unique 'job id' in the mysql database, so they're viewed as unique. I could exclude the job id and make the rest of the columns DISTINCT, which gives me the filtered rows I'm looking for (since literally every data point is identical except for the job id), however I need the job ID since it's the primary reference point for each invoice and is what I point to for: approvals, edits, etc.
So my question is, how can I filter out 'near' duplicate rows in my query, while still pulling in the job id for each ticket?
The current query is below:
SELECT * FROM jobs, users
WHERE jobs.job_csuper = users.user_id
AND users.user_email = '".$login."'
AND jobs.job_approverid1 = '0'
Thanks for looking into it!
Edit (examples provided):
This is what I meant by 'near duplicate'
Job_ID - Job_title - Job_user - Job_time - Job_date
2345 - Worked on circuits - John Smith - 1.50 - 2013-01-01
2344 - Worked on circuits - John Smith - 1.50 - 2013-01-01
2343 - Worked on circuits - John Smith - 1.50 - 2013-01-01
So everything is identical except for the Job_ID column.
You want a group by:
SELECT *
FROM jobs, users
WHERE jobs.job_csuper = users.user_id
AND users.user_email = '".$login."'
AND jobs.job_approverid1 = '0'
group by <all fields from jobs except jobid>
I think the final query should look something like this:
select min(Job_ID) as JobId, Job_title, user.name as Job_user, Job_time, Job_date
FROM jobs join users
on jobs.job_csuper = users.user_id
WHERE jusers.user_email = '".$login."' AND jobs.job_approverid1 = '0'
group by Job_title, user.name, Job_time, Job_date
(This uses ANSI syntax for joins and is explicit about the fields coming back.)
It's better to prevent the double submission.
Given that you cannot prevent the double submission...
I would query like this:
select
min(Job_ID) as real_job_id
,count(Job_ID) as num_dup_job_ids
,group_concat(Job_ID) as all_dup_job_ids
,j.Job_title, j.Job_user, j.Job_time, j.Job_date
from
jobs j
inner join users u on u.user_id = j.job_csuper
where
whatever_else
group by
j.Job_title, j.Job_user, j.Job_time, j.Job_date
That includes more than you explicitly asked for. But it's probably good to be reminded of how many dups you have, and it gives you easy access to the duplicate id info when you need it.
How about creating a hash for each row and comparing them:
`SHA1(concat_ws(field1, field2, field3, ...)) AS jobhash`