fetch data employee table with 1 id and multiple transaction id - mysql

here in transaction table one employee have multiple transaction .i want all transaction of 1 specific employee .but employee id should be print once in column .here is format
1.here one employee have more than one transaction id .id should display 1 time and display all transaction
desired result: employee details should display in one row but transaction id in multiple row
error id repeating id:
Copied from comments:
select
b.TransactionId,
a.Name
from
TransactionRecharge b
left JOIN Customer a on a.Id=b.CustomerId
where
b.CustomerId=101282

This is not a Good practice, I am pretty sure that "I am going to get negative marks for helping you", Anyway i just did for what you asked.
Below Query using ROW_NUMBER will help you get what you need exactly.
CREATE TABLE #customer(Id INT PRIMARY KEY,Name VARCHAR(255))
CREATE TABLE #TransactionRecharge(TransactionId VARCHAR(255),CustomerId INT FOREIGN KEY REFERENCES #customer(id))
INSERT INTO #customer
VALUES (1,'Raj'),(2,'Bala'),(3,'Chandra')
INSERT INTO #TransactionRecharge
VALUES ('reansaction1',1),('reansaction2',1),
('reansaction3',1),('reansaction4',1),
('reansaction5',1),('reansaction6',1),
('reansaction7',1),('reansaction8',2)
SELECT
CASE
WHEN ROW_NUMBER() OVER ( PARTITION BY a.id ORDER BY b.TransactionId,a.Id) = '1' THEN CONVERT(VARCHAR,a.Id)
ELSE ''
END AS Customer,
CASE
WHEN ROW_NUMBER() OVER ( PARTITION BY a.id ORDER BY b.TransactionId,a.Id) = '1' THEN Name
ELSE ''
END AS Name,
b.TransactionId
FROM
#TransactionRecharge b
LEFT JOIN
#customer a ON a.Id = b.CustomerId
WHERE 1 = 1
--AND b.CustomerId = 1
DROP TABLE #customer
DROP TABLE #TransactionRecharge

Related

Sequence in linked list data for mysql version 5.4

I have the following table structure.
Here starting with cover_id=from_id I need the sequence of the items id's in a seperate column. The expected output is as follows:
So the sequencing here is like: when cover_id = from_id start the sequence(0) and get the to_id in that row(310237) and check this in the id column and mark that row as next number(1) in the sequence again get the to_id of that row(310238) and check back in id column and mark it as next number(2) and so on.. when there is no to_id/Null in the to_id sequencing will end.
I tried to use the self left join - it didn't worked.
select A.id,A.cover_id,A.from_id,A.to_id, B.id, B.cover_id, B.from_id,B.to_id
from tableA A left join tableA B on A.to_id = B.id where A.cover_id=4655709 order by A.to_id desc limit 10;
Added the create table and insert script for reference.
Create table TableA (
id int,
cover_id int,
from_id int,
to_id int
)
Insert into TableA(id, cover_id,from_id,to_id)
values(310241, 4655709, 3962705, 310242),
(310238,4655709,4208771,310239),
(310242,4655709,4549272,NULL),
(310237,4655709,4613179,310238),
(310239,4655709,4613184,310240),
(310240,4655709,4613186,310241),
(310236,4655709,4655709,310237)

Find errors in a sequence

I have an activity changelog of officers that become active/inactive.
OfficerID ChangeTo ChangeDate
1 active 2017-05-01
1 active 2017-05-02
1 inactive 2017-05-04
6 active 2013-09-09
6 inactive 2016-04-14
6 recruit 2016-06-22
6 active 2016-06-23
6 inactive 2017-04-30
In the case above, officer id 1 is active from 1st of May until the 4th of May.
This is essentially a 'housekeeping' task. The second row is not required and should be deleted. I would like to do this within a MySQL procedure that is linked an event on a schedule. I need a query that can identify these rows, but I'm not sure how.
In a previous system, I had looped through an ordered list and compared the current value against the previous row's value. I have read that loops in MySQL are not encouraged, so I'm trying to figure out how to do this with queries alone.
I tried the following:
SELECT
a.ActivityID, a.OfficerID, a.ChangeTo, a.ChangeDate
FROM
tbl_Officers_Activity as a
INNER JOIN tbl_Officers_Activity AS b
ON a.OfficerID = b.OfficerID
AND a.ChangeDate > b.ChangeDate
AND a.ChangeTo = b.ChangeTo
INNER JOIN tbl_Officers_Activity AS c
ON a.OfficerID = c.OfficerID
AND a.ChangeDate < c.ChangeDate
AND a.ChangeTo <> c.ChangeTo
ORDER BY
OfficerID,
ChangeDate;
I was hoping I could somehow embed the criteria I need into the joins, but I'm at a loss. any help would be greatly appreciated.
This is what you need
SQLFIddle Demo
select a1.officerid,a1.changedate,a1.changeto_a as changeto
From
(select a.officerid,a.changedate,max(a.changeto) as changeto_a,count(*) as rnk
from tbl_Officers_Activity a
inner join tbl_Officers_Activity b
on a.OfficerID=b.OfficerID
and a.ChangeDate>=b.ChangeDate
group by a.officerid,a.changedate) a1
left join
(select a.officerid,a.changedate,max(a.changeto) as changeto_b,count(*) +1 as rnk
from tbl_Officers_Activity a
inner join tbl_Officers_Activity b
on a.OfficerID=b.OfficerID
and a.ChangeDate>=b.ChangeDate
group by a.officerid,a.changedate) b1
on a1.officerid=b1.officerid
and a1.rnk=b1.rnk
where changeto_a = changeto_b
Explanation:
MySQL doesn't have row_Number function, so first I had to derive it. I used this query to get row_number, which is names as rnk in the query. Call the table a1.
(select a.officerid,a.changedate,max(a.changeto) as changeto_a,count(*) as rnk
from tbl_Officers_Activity a
inner join tbl_Officers_Activity b
on a.OfficerID=b.OfficerID
and a.ChangeDate>=b.ChangeDate
group by a.officerid,a.changedate)
Now as MySQL doesn't have LEAD function also, I derived it by using the above query again, and changing the rnk to rnk+1, calling it b1.
Now to replicate LEAD, I left joined a1 with b1
Now using a where clause to find same changeto, you can get your output.
My solution in the end was similar to what Utsav posted, however, after comparing his solution to mine, I found mine to be accurate, and his inaccurate.
For my solution, I create a temporary table for the initial ordered list with an auto incremental primary key. Then clone the temp table and join on itself with the primary pk equal to itself +1 and also equal to the status change.
my procedure ends up like this:
-- create temp table
DROP TABLE IF EXISTS tmp_act;
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_act (
AutoID INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
ActivityID INT(11),
OfficerID INT(11),
ChangeTo text
);
-- temp data
insert into tmp_act (ActivityID,OfficerID,ChangeTo)
SELECT
a.ActivityID, a.OfficerID, a.ChangeTo
FROM
tbl_Officers_Activity as a
ORDER BY
OfficerID,
ChangeDate;
-- housekeeping
DROP TABLE IF EXISTS tmp_act1;
DROP TABLE IF EXISTS tmp_act2;
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_act1 AS (SELECT * FROM tmp_act);
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_act2 AS (SELECT * FROM tmp_act);
SELECT
a.AutoID, a.ActivityID, a.OfficerID, a.ChangeTo
FROM
tmp_act1 as a
INNER JOIN tmp_act2 AS b
ON a.OfficerID = b.OfficerID
AND a.ChangeTo = b.ChangeTo
AND a.AutoID = b.AutoID+1;

SQL select rows that have one value but not another

I have a table in SQL which will contain multiple rows for one id, as below
accountid Productname
1 GL
1 IP
1 MI
2 GL
2 IP
2 PA
3 MI
3 CP
3 IP
4 GL
4 CP
4 CI
I want to be able to select all accounts which have certain products but not other. For example all that have IP or GL but not MI, using the sample table above this would return accounts 2 and 4.
SELECT ccx_accountidname
FROM (
SELECT ccx_accountidname, ccx_productname
FROM Filteredccx_leadresearch
WHERE ccx_productname IN ('GL','IP')
AND ccx_accountidname IS NOT NULL
) AS T
WHERE ccx_productname NOT IN ('MI')
ORDER BY ccx_accountidname
and
SELECT DISTINCT LR1.ccx_accountidname
FROM Filteredccx_leadresearch LR1
LEFT JOIN Filteredccx_leadresearch LR2 ON LR1.ccx_accountid = LR2.ccx_accountid
AND LR2.ccx_productname IN ('GL', 'IP')
WHERE LR1.ccx_productname NOT IN ('MI')
AND LR1.ccx_accountidname IS NOT NULL
ORDER BY LR1.ccx_accountidname
Both give basically the same results, is there any way this can be done?
Thanks in advance for any help
Could you try this:
SELECT DISTINCT T1.Accountidname FROM TheTableThatContainsAccountnames as T1
JOIN AccountProductsTable as T2 on T1.AccountId=T2.AccountId
WHERE T2.ProductName = 'ProductYouWant'
AND T2.ProductName = 'AnOtherProductYouWant'
According to your post, all you really need is a simple query with the correct and logic. You want all accounts with Product name GL or IP but not in MI. This will do it without any other joins.
SELECT ccx_accountidname
FROM Filteredccx_leadresearch
WHERE
ccx_productname in ('GL','IP')
and ccx_productname not in ('MI')
EDIT
This will get you the account, though I doubt it will work in your overall solution. It's just hard to tell without seeing your complete dataset. This could be done with parameters too.
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
DROP TABLE #TempTable
IF OBJECT_ID('tempdb..#TempTableTwo') IS NOT NULL
DROP TABLE #TempTableTwo
create table #TempTable (accountid int, productname char(2))
insert into #TempTable (accountid,productname) values
(1,'GL'),
(1,'IP'),
(1,'MI'),
(2,'GL'),
(2,'IP'),
(2,'MA')
select distinct
t1.accountid,
1 as T
into #TempTableTwo
from
#TempTable t1
where
productname in ('GL','IP')
union all
select distinct
t1.accountid,
-1 as T
from
#TempTable t1
where
productname in ('MI')
select
accountid
from #TempTableTwo
group by accountid
having sum(T) > 0
I might be late for the game, but this should do the trick, if anyone is trying to solve a similar problem. I renamed your table and it's columns:
Filteredccx_leadresearch -> l_search
ccx_accountidname -> a_name
ccx_productname -> p_name
And here's the SQL:
(SELECT DISTINCT t1.a_name
FROM l_search t1
JOIN l_search t2 ON t1.a_name = t2.a_name
WHERE t1.p_name = 'IP'
OR t2.p_name = 'GL')
MINUS
(SELECT DISTINCT t1.a_name
FROM l_search t1
JOIN l_search t2 ON t1.a_name = t2.a_name
WHERE ((t1.p_name = 'IP'OR t1.p_name = 'GL') AND t2.p_name = 'MI')
OR
(t1.p_name = 'MI' AND (t1.p_name = 'IP' OR t1.p_name = 'GL')));
First set:
cross product of table on itself with same IDs, get account IDs which have a product 'IP' or 'GL'.
Second set:
cross product of table on itself with same IDs, get account IDs which have p_name ('IP' OR 'GL') on first cross property AND 'MI' on second.
Also, get those IDs, which have the same but the other way around: p_name 'MI' on first cross property AND ('IP' OR 'GL') on second.
And finally subtract the second from the first.
Here is a simple way to include the accounts that match either IP or GL and exclude those accounts if they have an record for MI without using a subquery.
This is assuming t1 is a table that has unique account numbers in accountid and t2 is the table you have shown above that has accountid and Productname columns.
SELECT DISTINCT
t1.accountid
FROM t1
LEFT JOIN t2 AS t2_match
ON t1.accountid = t2_match.accountid
AND
(
t2_match.Productname = 'IP'
OR t2_match.Productname = 'GL'
)
LEFT JOIN t2 AS t2_not_match
ON t1.accountid = t2_not_match.accountid
AND t2_not_match.Productname = 'MI'
WHERE
t2_match.accountid IS NOT NULL
AND t2_not_match.accountid IS NULL
This is really late, but it might help some one.
I'll focus only on using the columns we have on the table we are shown (won't combine it with other tables we were not given).
Since the only table in the example is not clearly named, I'll call it some_table
SELECT t.accountidname, t.productname
FROM some_table t
WHERE t.productname IN ('GL','IP')
AND t.accountidname NOT IN (
SELECT accountidname
FROM some_table
WHERE productname = 'MI'
);
The idea here is to:
Select all accountid and productname that have productname either GL or IP (3rd line)
Select all accountid that have a productname MI and remove them from the values we already have (4th line onwards)
With this values, filtering or combining it with other tables should be rather trivial.
You might want to replace the SELECT with SELECT DISTINCT if the combinations of accountid and productname could be repeated in the table.

looking for most efficient way to to query multiple email addresses in Mysql

I'm looking for a way to select the email address of joe so that every time i run a select query I get only one email address returning in sequence of the id. sort of round Robin the results ..
so on first select I get joe#blogs.com
and then second I get joe#gmail.com
and third joe#outlook.com
and next joe#blogs.com as there are only three entries
If you know what I mean.
addresses
---------------------
id|name|email
---------------------
1 |joe |joe#blogs.com
2 |joe |joe#gmail.com
3 |joe |joe#outlook.com
Give this a shot:
CREATE TABLE #results (id INT, name VARCHAR(50), email VARCHAR(100))
DECLARE #currentID INT;
WHILE(1 = 1)
BEGIN
SET #currentID =
(SELECT TOP 1 t.id
FROM [YOURTABLE] t
LEFT JOIN #results r
ON r.id = t.id
WHERE t.name = 'joe'
AND r.id IS NULL)
IF #currentID IS NULL
BREAK;
SELECT * FROM [YOURTABLE] WHERE id = #currentID
INSERT INTO #results
SELECT TOP 1 t.id, t.name, t.email
FROM [YOURTABLE] t
WHERE t.id = #currentID
END
I think the best way would be to store the next email id in a field that has a foreign key to the user. This will give you the most interoperability between whatever will be using the database.
Be mindful because you will run into issues if emails are deleted.

Mysql insert records from table A to table B. if table B.column is less than

**Employee**
PK empId
firstName
lastName
isRegularEmp
**Employee_Training**
PK FK empId
PK FK trainingId
logId
**Training**
PK TrainingId
date
specialEmployeesNeeded
regularEmployeesNeeded
FK roomId
I am trying to insert all the employees into the employee_training table by a specific date. It works except that I have a required amount not to surpass which is the SpecialEmployees/ Regular Employees field value.
For instance I have 200 Regular Employees and 100 Regular Employees in the Employee Table but I only need 35 Special Employees and 5 Reegular Employees to be inserted as specified in the training table.
I tried HAVING but it keeps throwing an error unknown column. Please help, I tried inserting one type of employee , but it still doesn't work
INSERT INTO EMPLOYEE_TRAINING(empId, trainingId)
SELECT E.empId , T.TrainingId
FROM EMPLOYEE E, TRAINING T
WHERE T.`date` = "2013-4-20"
AND E.isRegularEmp = false
HAVING COUNT(E.empId) <= regularEmployeesNeeded
I can't post my erd because I don't have enough points.
regularEmployees is not a column in any of your tables nor is it defined anywhere in your query. Try
INSERT INTO EMPLOYEE_TRAINING(empId, trainingId)
SELECT E.empId , T.TrainingId
FROM EMPLOYEE E, TRAINING T
WHERE T.`date` = "2013-4-20"
AND E.isRegularEmp = false
HAVING COUNT(E.empId) <= (select count(*) from EMPLOYEE where isRegularEmp=true )
The placement of your isRegularEmp condition is incorrect. It should be placed in the WHERE clause.
INSERT INTO EMPLOYEE_TRAINING(empId, trainingId)
SELECT E.empId , T.TrainingId
FROM EMPLOYEE E, TRAINING T
WHERE T.`date` = "2013-4-20"
AND E.isRegularEmp = false
HAVING COUNT(E.empId) <= regularEmployees
EDIT: As pointed out in Michael Benjamin's answer, regularEmployees is not a field is not defined. You need to SELECT the COUNT of regular employees.
INSERT INTO EMPLOYEE_TRAINING(empId, trainingId)
SELECT E.empId , T.TrainingId
FROM EMPLOYEE E, TRAINING T
WHERE T.`date` = "2013-4-20"
AND E.isRegularEmp = false
HAVING COUNT(E.empId) <= (SELECT COUNT(*) FROM EMPLOYEE WHERE isRegularEmp = true)