In my db, I have a "sales" table and a "sales_item". Sometimes, something goes wrong and the sale is recorded but not the sales item's.
So I'm trying to get the salesID from my table "sales" that haven't got any rows in the sales_item table.
Here's the mysql query I thought would work, but it doesn't:
SELECT s.*
FROM sales s NATURAL JOIN sales_item si
WHERE s.date like '" . ((isset($_GET['date'])) ? $_GET['date'] : date("Y-m-d")) . "%'
AND s.sales_id like '" . ((isset($_GET['shop'])) ? $_GET['shop'] : substr($_COOKIE['shop'], 0, 3)) ."%'
HAVING count(si.sales_item_id) = 0;
Any thoughts?
Where does the table alias v does come from?
Showing the table definition would be a really good idea ;)
It has to be a left join:
SELECT *
FROM table1
LEFT JOIN table2 ON(table1.id = table2.table1_id)
WHERE table2.table1_id IS NULL
Table1 is your sales-Table and table2 is you sales_item
Having always used with Group By
GROUP BY si.sales_item_id
HAVING count(si.sales_item_id) = 0;
You don't need to join the tables, you can use something like:
[...] WHERE sales.id NOT IN (SELECT sales_id FROM sales_item)
This filters only the sales that do not have any corresponding sales_item entries.
For completeness ....
SELECT S.*
FROM SALES S
WHERE NOT EXISTS (
SELECT 1
FROM SALES_ITEM SI
WHERE SI.SALES_ITEM_ID = S.ID)
MySQL can have issues with IN clauses.
Assuming that each item in sales_item has an associated sales_id against it, you are probably looking for all sales that have no items.
How about using a subquery? Get all the sales_ids from the sales table where the id does not exist in the items table...
SELECT * from sales where sales_id not in (SELECT DISTINCT sales_id from sales_item)
(note : Exact syntax may be wrong, but the idea should be sound, if I understood the question correctly)
The join is restricting the rows to be displayed.
My advice is to forget about the join and use instead something like this:
select *
from sales
where salesId not in (select salesId from sales_item)
Basically, returns sales that doesn't have any associated sales_item.
Good luck
You should probably group rows by sales item id.
SELECT s.id, count(*) as no_of_items
FROM sales s NATURAL JOIN sales_item si
WHERE s.date like '" . ((isset($_GET['date'])) ? $_GET['date'] : date("Y-m-d")) . "%'
AND v.sales_id like '" . ((isset($_GET['shop'])) ? $_GET['shop'] : substr($_COOKIE['shop'], 0, 3)) ."%'
GROUP BY si.salesitem_id
HAVING no_of_items = 0;
Related
I have two databases
TABLE_ORDERS with id,created,user_id.....status_id
TABLE_STATUSES with it,title,ordering,month
ordering is an integer for ordering statuses and month is the month number (01-January, 02-February, ...)
I would like to create somethig like:
SELECT *
FROM TABLE_ORDERS,
TABLE_STATUSES
WHERE 1
AND TABLE_STATUSES.month >= '7'
ORDER BY TABLE_STATUSES.ordering
What should be the right syntax?
The wished result is a table of orders ordered by statues like "To be delivered on January, To be delivered on February" that will change automatically month by month.
Thank you for your support!
I think you should try
Select * from TABLE_ORDERS o inner join TABLE _STATUSES s ON o.id=s.id WHERE MONTH(s.month)>=7 ORDER BY s.ordering.
You can filter out months gretter than 7.
Good luck.
your query can go like this :
SELECT TABLE_ORDERS.*, TABLE_STATUSES.month
FROM TABLE_ORDERS INNER JOIN TABLE_STATUSES
ON TABLE_STATUSES.id = TABLE_ORDERS.status_id
ORDER BY TABLE_STATUSES.ordering
An example can be :
SELECT column_list
FROM table_1
INNER JOIN table_2 ON table_1.columnname = table_2.columnname;
I would like to know how I can write a SQL Script so a within a group of individuals initially selected:
SELECT [RECORDS].[CONSTITUENT_ID]
,[RECORDS].[FIRST_NAME]
,[RECORDS].[LAST_NAME]
,[DATEADDED]
,[DTE]
,[Amount]
,[REF]
,[TYPE]
FROM [re7].[dbo].[GIFT]
INNER JOIN [re7].[dbo].[RECORDS]
ON GIFT.CONSTIT_ID LIKE RECORDS.ID
WHERE ([DTE] BETWEEN '2/7/2015' AND '2/8/2015')
ORDER BY [DATEADDED] DESC
select only individuals who are "First Time Donors" (or someone who only has one gift in [re7].[dbo].[GIFT].
[RECORDS] is a table of all the constituents.
[GIFT] is a table of all recorded Gifts.
The output of the above Query, is just a table with:
CONSTITUENT_ID, FIRST_NAME, LAST_NAME, DATEADDED, DTE, Amount, REF, TYPE
I pretty much want to see the same output format, but I would like the query to select only CONSTITUENT_ID who only have 1 GIFT (by their Record ID) in [re7].[dbo].[GIFT].
I apologize for the lack of data to show. I wish I could describe better....
SELECT [RECORDS].[CONSTITUENT_ID]
,[RECORDS].[FIRST_NAME]
,[RECORDS].[LAST_NAME]
,[DATEADDED]
,[DTE]
,[Amount]
,[REF]
,[TYPE]
FROM [re7].[dbo].[GIFT]
INNER JOIN [re7].[dbo].[RECORDS]
ON GIFT.CONSTIT_ID LIKE RECORDS.ID
WHERE ([DTE] BETWEEN '2/7/2015' AND '2/8/2015')
AND GIFT.CONSTIT_ID IN (
SELECT CONSTIT_ID FROM re7.dbo.Gift GROUP BY CONSTIT_ID HAVING COUNT(*) = 1
) /* another option is to add a subquery to the query you already had */
ORDER BY [DATEADDED] DESC
This solution simply selects all the constituents who have made only one donation and then joins to that, thereby limiting the result set.
SELECT
r.[CONSTITUENT_ID]
,r.[FIRST_NAME]
,r.[LAST_NAME]
,[DATEADDED]
,[DTE]
,[Amount]
,[REF]
,[TYPE]
FROM
(select [CONSTIT_ID] from [re7].[dbo].[GIFT] group by [CONSTIT_ID] having count([CONSTIT_ID]) = 1) g1
inner join [re7].[dbo].[GIFT] g
on g.[CONSTIT_ID] = g1.[CONSTIT_ID]
INNER JOIN [re7].[dbo].[RECORDS] r
ON g.CONSTIT_ID LIKE r.RECORDS.ID
WHERE ([DTE] BETWEEN '2/7/2015' AND '2/8/2015')
ORDER BY [DATEADDED] DESC
This is something I'm trying to get my head around... I have three tables like this:
Practice
* PracticeID
* PracticeName
Group
* GroupID
* Sales
* Salaries
* Overheads
Values
* PracticeID
* GroupID
* Income
* Expense
What I am looking to do is prepare a view to sum up the income and expenses in Values by the group names in the Group table. I can get as far as a row by row summary, but I'm having the issue on how to include the group clause in the code I currently have, which is below:
SELECT Practice.PracticeName, Group.Groupname, Values.Income, Values.Expenses
FROM values INNER JOIN
Practice ON values.PracticeID = Practice.PracticeID INNER JOIN
Group ON Values.NominalGroupID = Group.GroupID
try this:
SELECT Practice.PracticeName, Group.Groupname, SUM(Values.Income) as SumIncome, SUM(Values.Expenses ) as SumExpences
FROM values INNER JOIN
Practice ON values.PracticeID = Practice.PracticeID INNER JOIN
Group ON Values.NominalGroupID = Group.GroupID
Group By Group.Groupname
Your table definition does not really include all the columns you used in your example so I'm not sure if that's what you are looking for:
SELECT Group.Groupname
,SUM(Values.Income) as Income
,SUM(Values.Expenses ) as Expenses
FROM Group
INNER JOIN Value ON Values.GroupID = Group.GroupID
Group By Group.Groupname
I have the following query
SELECT *
FROM attend
RIGHT OUTER JOIN noattend ON attend.date = noattend.date2
WHERE attend.date
BETWEEN '2010-02-01'
AND '2010-04-01'
AND attend.customerid =1
ORDER BY date DESC
LIMIT 0 , 30
Attend is the table with customerid
noattend is the table with a row for each date (date2) I followed the advice in other questions to right outer join it to create values where there is no record in attend but it still isn't filling in the empties
any help much appreciated
If you say that noattend is a table with a row for each date, you should use it in WHERE clause:
WHERE noattend.date2 BETWEEN (.....
And I think it's more clear to use LEFT JOIN :
SELECT *
FROM noattend
LEFT OUTER JOIN attend ON (attend.date = noattend.date2 AND attend.customerid =1)
WHERE noattend.date2
BETWEEN '2010-02-01'
AND '2010-04-01'
ORDER BY date DESC
LIMIT 0 , 30
You need to get rid of the SELECT * and list your column names instead. Where you want the date to be, use the field noattend.date2, not attend.date. Attend.date will be NULL (blank) for those extra rows created to fill in your "missing" dates.
Something like:
SELECT attend.id, attend.name, noattend.date2
FROM . . . (continue your code here)
Can someone help me with this query:
SELECT su.name,su.imdb , su.id, su.owner, COUNT(*) AS count
FROM subhits AS h LEFT JOIN subtitles AS su ON h.subid=su.id
WHERE su.added BETWEEN '" . $lweek . "' AND '" . $today . "'
GROUP BY h.subid
ORDER BY count DESC LIMIT 15
RETURNS:
name imdb id owner count
*Angels and Demons WTV /title/tt0808151/ 3337 3055 120
Terminator Salvation 2009 /title/tt0438488/ 3539 26 120
Friday The 13th-WTV /title/tt0758746/ 3334 26 82
Night at the Museum /title/tt1078912/ 3548 7170 75
*Angels and Demons WTV2 /title/tt0808151/ 3512 12 10
*DUPLICATED IMDB
As you see it returns results with the same imdb.
What i would like to do is get the highest count, but exclude the lowest imdb count from the result.
What I like about MySQL compared to Oracle, is how other fields not part of GROUP BY can be selected without using grouping functions. What the query below does is take your query and groups it by imdb, which selects a unique imdb with the highest count (which would appear first in the descending sort in the subselect). Try it and see if it works for you.
SELECT name, imdb, id, owner, count
FROM
(
SELECT su.name,su.imdb , su.id, su.owner, COUNT(*) AS count
FROM subhits AS h LEFT JOIN subtitles AS su ON h.subid=su.id
WHERE su.added BETWEEN '" . $lweek . "' AND '" . $today . "'
GROUP BY h.subid
ORDER BY count DESC
)
GROUP BY imdb
LIMIT 15
This may help.
http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#101
I hate to say this, but this is one of those rare occasions where a temp table might help. If you put the results of this:
select
imdb,
id,
count(*) as cnt
from subtitles
group by
imdb,
id
..into a temp table, you can then get the rows you really want:
select
t.imdb,
t.id,
t.cnt
from MyTempTable t
inner join
(
select
imdb,
max(cnt) as maxcnt
from MyTempTable
group by
imdb
) as drv on t.imdb = drv.imdb and t.cnt = drv.maxcnt
..and the results of the above can be joined back into your main table without having to be grouped again.
Does this help?
Apologies for not putting all the SQL in but I'm pressed for time. This will do what you want but will still duplicate if the counts are the same. The query could be modified to deal with this if you care about it.
On a separate note, I'm not sure why you are left joining in the statement when you are not showing any data from the left hand table?
Try this:
SELECT su.name
, su.imdb
, su.id
, su.owner
, (SELECT COUNT(*) FROM dbo.subhits AS h WHERE h.subid = su.id) AS count
FROM dbo.subtitles AS su
ORDER BY count DESC LIMIT 15
Edit: Using the additional information provided I had an almost working solution but got stuck. Combining Chris Simpson's answer with the partial solution I came up with this. It avoids temp tables and has the missing pieces that the other Chris didn't have time to complete. I'm building this in MSSQL so it might need tweaking to work in MySQL. I also can't guarantee the information will be correct without your data but this might help.
SELECT a.id
, (SELECT su.name FROM dbo.subtitles su WHERE a.id = su.id LIMIT 1)
, a.imdb
, (SELECT su.owner FROM dbo.subtitles su WHERE a.id = su.id LIMIT 1)
, a.count
FROM
(
SELECT su.id
, su.imdb
, COUNT(*) AS count
FROM dbo.subtitles su
INNER JOIN dbo.subhits sh ON su.id = sh.subid
GROUP BY su.id, su.imdb
) a
INNER JOIN
(
SELECT c.imdb
, MAX(c.count) AS maxCount
FROM
(
SELECT su.id
, su.imdb
, COUNT(*) AS count
FROM dbo.subtitles su
INNER JOIN dbo.subhits sh ON su.id = sh.subid
GROUP BY su.id, su.imdb
) c
GROUP BY c.imdb
) b ON a.imdb = b.imdb AND a.count = b.maxCount
ORDER BY a.count DESC LIMIT 15
I'd try to test this myself, but I don't have your data or a good sample to test against.
SELECT su.name,su.imdb , su.id, su.owner, COUNT(*) AS counter
FROM subhits AS h LEFT JOIN subtitles AS su ON h.subid=su.id
WHERE su.added BETWEEN '" . $lweek . "' AND '" . $today . "'
GROUP BY h.subid
having max(counter)
ORDER BY count DESC LIMIT 15