I have two tables with invoice detail and serial numbers.
Both tables have invoice number, but when I attempt to join using left or inner join the amount duplicates in each lines. I want to list down all the serials associated with my invoice # in table 1 without duplicating the amount each lines. I'm currently using MS Access.
Thanks for the help.
Table 1
Invoice# amount
001 500
Table 2
Invoice# serial
001 123
001 456
001 789
001 1011
001 1213
Desired Output:
Invoice# amount serial
001 500 123
456
789
1011
1213
My Current Query Output:
Query:
Select invoice.invoice,invoice.amount,tblmachine.serial
From tblmachine inner join invoice on tblmachine.invoice =invoice.invoice;
Use UNION ALL for 2 queries.
The 1st will return the 1st row that you need and the 2nd all the rest:
select i.[invoice#], i.amount, min(t.serial) as serial
from tblmachine as t inner join invoice as i
on t.[invoice#] = i.[invoice#]
where i.[invoice#] = '001'
group by i.[invoice#], i.amount
union all
select null, null, t.serial
from tblmachine as t
where t.[invoice#] = '001'
and t.serial > (select min(serial) from tblmachine where [invoice#] = t.[invoice#])
Results:
invoice# amount serial
001 500 123
456
789
1011
1213
Can't do that desired output in query for multiple invoices.
Build a report and set textbox HideDuplicates property to Yes.
Related
I have a table with many data and a sample is as follows
product_table
data
data2
data3
data4
data5
data6
data7
product id
001
002
003
004
005
006
007
product name
a
b
c
d
e
f
g
status
available
not available
damaged
available
available
not available
damaged
order id
1
2
3
4
5
6
7
9
I need to extract 2 order ids from each of the statuses from one query.
The out put I want is as follows
status
order id
available
1
available
4
not available
2
not available
6
damaged
3
damaged
7
I tried using "Limit" but it only brings out the first few data which is in the table.
Query I used
Select order id , status
from table product_table
limit 2
;
output I got was
status
order id
available
1
not available
2
You can partition the database by status and use row_number to extract two records.
select status, order_id from (
select status, order_id, row_number() over (partition by status) as rn from product_table)
where rn <=2;
so I have 3 tables in my db, where all 3 tables contains a column which have similar data, but name of that column is different on all the 3 tables, below is an example.
Ban Table
user_id
ban_user_id
ban_date
reason
end_date
1300
1
xyz
xyz
xyz
32
1
xyz
xyz
xyz
43
2
xyz
xyz
xyz
Reports Table
user_id
last_modified_user_id
report_date
reason
end_date
1300
1
xyz
xyz
xyz
32
2
xyz
xyz
xyz
43
2
xyz
xyz
xyz
Warning Table
user_id
warning_user_id
warning_date
reason
end_date
1300
1
xyz
xyz
xyz
32
2
xyz
xyz
xyz
43
3
xyz
xyz
xyz
Now I want to fetch data by combining these 3 tables, where ban_user_id, last_modified_user_id, and warning_user_id contains the data of staff member who took the actions, so i want to group the data by the staff id.
The output i am looking for is as follows:
staff_id
total_reports
total_bans
total_warnings
1
1
2
1
2
2
1
1
3
0
0
1
where it is counting the data for each table by grouping the 2nd column, ban_user_id, last_modified_user_id, warning_user_id respectively. And than combining the data.
I tried things with UNION All and stuffs, but it didn't work out.
Thankyou in advance for your help
Use UNION ALL for all 3 tables and then aggregate:
SELECT staff_id,
COUNT(report) AS total_reports,
COUNT(ban) AS total_bans,
COUNT(warning) AS total_warnings
FROM (
SELECT last_modified_user_id AS staff_id, 1 AS report, null AS ban, null AS warning FROM Reports
UNION ALL
SELECT ban_user_id, null, 1, null FROM Ban
UNION ALL
SELECT warning_user_id, null, null, 1 FROM Warning
) t
GROUP BY staff_id;
Or:
SELECT staff_id,
SUM(report) AS total_reports,
SUM(ban) AS total_bans,
SUM(warning) AS total_warnings
FROM (
SELECT last_modified_user_id AS staff_id, 1 AS report, 0 AS ban, 0 AS warning FROM Reports
UNION ALL
SELECT ban_user_id, 0, 1, 0 FROM Ban
UNION ALL
SELECT warning_user_id, 0, 0, 1 FROM Warning
) t
GROUP BY staff_id;
See the demo.
You can use Table joins (Inner/outer/left/right) to get the data instead of union.
I'm assuming the staff_id is the equivalent of user_id column as you haven't mentioned anything about that, so your script will look something like this:
SELECT W.user_id AS staff_id,
B.ban_user_id,
R.last_modified_user_id,
W.warning_user_id
FROM Warning AS W
LEFT JOIN Reports AS R on R.user_id = W.user_id
LEFT JOIN Ban AS B on B.user_id = W.user_id
group by W.user_id
I want to filter the codes with at least 1 barcode with at least X occurrences in store table.
tables structure
table codes (now has 1.000 records):
code (PK)
ABC
XYZ
table barcodes (now has 6.000 records):
barcode (PK) code
ABC 123
ABC 456
XYZ 789
table store (now has 67.000 records):
id (PK) barcode
1 123
2 123
3 123
4 789
how can I speed up this query?
SELECT c.code,
IFNULL(
(SELECT COUNT(*) count FROM store s INNER JOIN barcode b ON s.barcode=b.barcode WHERE b.code=c.code GROUP BY a.barcode ORDER BY count DESC LIMIT 1
),0) max
FROM codes c
GROUP BY c.code";
HAVING max>=X
with x = 2 the expected result is:
code max
ABC 3
because only the code ABC has at least 1 barcode (123) with at least 2 occurrences in store table.
I try to use DISTINCT to avoid duplication of the data, but no work.
How to avoid the duplicate data?
Table 1
Employee code Deduction Voucher no Dec_Amount
001 999 50
001 888 20
002 777 100
Table 2
Employee code Payslip Voucher No Pay_Amount
001 111 100
002 222 200
The output should be:
Employee code Deduction Voucher no Dec_Amount Payslip Voucher No Pay_Amount
001 999 50 111 100
001 888 20
002 777 100 222 200
But i got the table like this.
Employee code Deduction Voucher no Dec_Amount Payslip Voucher No Pay_Amount
001 999 50 111 100
001 888 20 111 100
002 777 100 222 200
You cannot get those results with just a SQL query. It seems to me you need it in this format for display in a table/excel spreadsheet. If this is the case you would have to handle the "Hiding" of the particular entries with some other code. The reason is because the entries you want to hide are correctly associated with the 001 employee.
While I do agree this probably makes a lot more sense to do in your front end code, it is possible to do in SQL. Using a variable you get a function similar to SQL Server's ROW_NUMBER function and then only join on the first row per employee code.
See the sqlfiddle - http://sqlfiddle.com/#!2/47302/11
SELECT t1.`Employee code`,`Deduction Voucher no`,`Dec_Amount`,
COALESCE(`Payslip Voucher No`,'') as `Payslip Voucher No`,
COALESCE(CAST(`Pay_Amount` as char(10)),'') as `Pay_Amount`
FROM Table2 t2
RIGHT JOIN
(
SELECT #row_num := IF(#prev_value=`Employee code`,#row_num+1,1) AS RowNumber
,`Employee code`,`Deduction Voucher no`,`Dec_Amount`
,#prev_value := `Employee code`
FROM Table1,
(SELECT #row_num := 1) x,
(SELECT #prev_value := '') y
ORDER BY `Employee code`
) t1
ON t1.`Employee code`=t2.`Employee code` AND t1.RowNumber=1
To expand on #d.lanza38's answer, there is no way given for the DB to tell which row in table1 should get the data from table2. Remember that there is no order to the data in the database, so there is no inherent concept of "the first row with employee code 001".
A standard (inner) join will put them as you have shown - on both. Which is actually correct - your table structures say that for every payslip in table2, there can be many deductions. So if you want the data from both tables, the deductions have to have the matching payslip data attached.
You can't use DISTINCT to magically fix your data - you need to understand the data structures, and relate them correctly.
To get what is in your example (which may be wrong) try this SQL:
select
a.Employee_code,
Deduction_Voucher_no,
Dec_Amount,
Payslip_Voucher_No,
Pay_Amount
from
table1 as a
inner join table2 as b on a.employee_code = b.employee_code
where Deduction_Voucher_no = (
select max(Deduction_Voucher_no)
from table1 as c
where a.Employee_code = c.Employee_code)
UNION
select
a2.Employee_code,
Deduction_Voucher_no,
Dec_Amount,
null as Payslip_Voucher_No,
null as Pay_Amount
from
table1 as a2
inner join table2 as b2 on a2.employee_code = b2.employee_code
where Deduction_Voucher_no <> (
select max(Deduction_Voucher_no)
from table1 as c2
where a2.Employee_code = c2.Employee_code)
order by 1,2 desc
Note: untested, because I don't have your database, and don't even know which database engine you are using. If it complains about selecting nulls, replace with 0 or '' depending upon the data type.
UPDATE improved SQL and provided a fiddle: http://sqlfiddle.com/#!2/e7fc2/2
I have a mysql database structured like:
table transactions:
id paymentid clientid status
------------------------------
1 001 12345 0
2 002 11223 1
3 003 12345 4
4 004 12345 4
What is the most efficient way to run a query in mysql to give me the number of times a certain clientid had payments with the status of 4?
like:
select clientid, count(*)
where status = 4
but only return the count of a specific clientid.
You will just add a WHERE filter for clientId if you want to filter by a specific client. If not, then you can remove the and clientid = 12345:
select clientid, count(*)
from transactions
where status = 4
and clientid = 12345
GROUP BY clientId;
See SQL Fiddle with Demo