Let's supouse that I have 1 table with PRODUCTS. And each product are lated to a "gender" (Female (1) or Male (2))
That Products have a boolean attribute that indicate if that product is or isn't in OFFER.
Explain example:
ID_PRODUCT, GENDER, OFFER
1, 2 (male), 0
2, 2 (male), 1
3, 2 (male), 1
4, 1 (female), 1
5, 1 (female), 1
6, 2 (male), 1
I need to get all the Offers, but "intercalated" (I don't know how say it on English... hehe)... One male, one female, one male, one female, one male... And ONLY THE OFFERS.
In this example, the response show be:
2, 2(m), 1
4, 1(f), 1
3, 2(m), 1
5, 1(f), 1
6, 2(m), 1
SELECT * FROM products WHERE offer = 1 ORDER BY ¿what?
Can I do that?
Thanks a lot in advance!
Try:
SELECT p.*,
IF(`GENDER`='2 (male)',#m:=#m+1,#f:=#f+1) As position
FROM Products p,
(SELECT #m:=0,#f:=0) x
WHERE `OFFER` = 1
ORDER BY position, `GENDER` DESC
Demo: http://sqlfiddle.com/#!2/6671ea/4
Related
I have two tables:
BusinessViews:
id
createdAt
businessId
userId
1
2022-01-19 18:00:00
1
1
2
2022-01-19 18:02:00
1
1
3
2022-01-19 18:05:00
1
1
4
2022-01-19 18:05:50
1
1
5
2022-01-19 18:07:00
1
1
6
2022-01-19 18:08:00
1
1
7
2022-01-19 18:10:00
1
1
BusinessClients:
id
status
createdAt
userId
createdBy
businessId
1
1
2022-01-19 18:01:00
1
1
1
2
2
2022-01-19 18:03:00
1
2
1
3
0
2022-01-19 18:06:00
1
1
1
4
1
2022-01-19 18:07:30
1
1
1
5
0
2022-01-19 18:09:00
1
2
1
The BusinessViews is for register the business page views by users and BusinessClients for the clients history. To get the count of total page views for businessId = 1 for example I simply did this:
SELECT COUNT(*)
FROM BusinessViews
WHERE businessId = 1
GROUP BY businessId
Result: 7
But now I want to segment this result to get the count of views made by clients and the count of views made by non-clients users at the moment of view. For that, let me explain the dynamics of BusinessClients: with this table users can request to be clients of any business and the business employees can refuse/accept (in case of request) and remove (in case of the user is already a client). If the user has no records in the table it's because he was never a client of the business and if the user has records in the table they can have three types of status:
status = 1 means user sent the request to business (If the user
does not have records yet, this is the only possibility)
status = 2 means user request was accepted by a business employee
status = 0 if userId = createdBy means user leaved the business
and if userId != createdBy means employee refused the request (if previous status = 1) or removed user of the business (if previous status = 2)
Taking that into account, the result I would like to get is:
Client views: 2
Non-client views: 5
I know I have to work with BusinessClients.status and BusinessClients.createdAt ranges according to BusinessViews.createdAt value. But I'm completely out of ideas on how to do this query. I don't know if I should use left join or subqueries and I can't think of any way to get these results.
What is the correct way to do this?
UPDATE:
Explaining the desired result: I have 7 views and I want to know how many of these views came from clients and non-clients users at the moment of the view (I'm using only one userId to simplify understanding but there may be multiple users registering views in BusinessViews table and joining and leaving BusinessClients table), so:
BusinessView with id = 1 was created at 2022-01-19 18:00:00 and at this moment the corresponding user is not a client yet (because he was never a client), so:
Client Views: 0 and Non-client views: 1.
BusinessView with id = 2 was created at 2022-01-19 18:02:00 and at this moment the corresponding user is not a client yet again (because the current status still = 1 at this time and only changed at 2022-01-19 18:03:00 (BusinessClient with id = 2), so:
Client Views: 0 and Non-client views: 2.
BusinessView with id = 3 was created at 2022-01-19 18:05:00 and at this moment the corresponding user is already a client (because status = 2 was created at 2022-01-19 18:03:00 (BusinessClient with id = 2) and only changed at 2022-01-19 18:06:00 (BusinessClient with id = 3), so:
Client Views: 1 and Non-client views: 2.
BusinessView with id = 4 same as previous item, so:
Client Views: 2 and Non-client views: 2.
BusinessView with id = 5 was created at 2022-01-19 18:07:00 and at this moment the corresponding user is not a client anymore (because status = 0 was created at 2022-01-19 18:06:00 (BusinessClient with id = 3) and only changed at 2022-01-19 18:07:30 (BusinessClient with id = 4), so:
Client Views: 2 and Non-client views: 3
BusinessView with id = 6 was created at 2022-01-19 18:08:00 and at this moment the corresponding user still not a client (because status = 1 was created at 2022-01-19 18:07:30 (BusinessClient with id = 4) and only changed at 2022-01-19 18:09:00 (BusinessClient with id = 5), so:
Client Views: 2 and Non-client views: 4.
BusinessView with id = 7 same as previous item (the only difference is that this is the last record so far), so
Client Views: 2 and Non-client views: 5.
The question is: where is the BusinessViews.createdAt between the BusinessClients.createdAt records and what is the corresponding BusinessClients.status for the user at BusinessViews.createdAt?
UPDATED
Thank you for adding the explanation of the join.
Client views: 2
Non-client views: 5
WITH BusinessViews (id, createdAt, businessId, userId) AS (
SELECT 1, '2022-01-19 18:00:00', 1, 1 UNION ALL
SELECT 2, '2022-01-19 18:02:00', 1, 1 UNION ALL
SELECT 3, '2022-01-19 18:05:00', 1, 1 UNION ALL
SELECT 4, '2022-01-19 18:05:50', 1, 1 UNION ALL
SELECT 5, '2022-01-19 18:07:00', 1, 1 UNION ALL
SELECT 6, '2022-01-19 18:08:00', 1, 1 UNION ALL
SELECT 7, '2022-01-19 18:10:00', 1, 1
), BusinessClients (id, status, createdAt, userId, createdBy, businessId) AS (
SELECT 1, 1, '2022-01-19 18:01:00', 1, 1, 1 UNION ALL
SELECT 2, 2, '2022-01-19 18:03:00', 1, 2, 1 UNION ALL
SELECT 3, 0, '2022-01-19 18:06:00', 1, 1, 1 UNION ALL
SELECT 4, 1, '2022-01-19 18:07:30', 1, 1, 1 UNION ALL
SELECT 5, 0, '2022-01-19 18:09:00', 1, 2, 1
)
SELECT
COUNT(CASE WHEN bcs.status IS NULL OR bcs.status <> 2 THEN 1 END) 'non-client-views',
COUNT(CASE WHEN bcs.status = 2 THEN 1 END) 'client-views'
FROM BusinessViews bv
LEFT JOIN LATERAL (
SELECT status
FROM BusinessClients bc
WHERE bc.businessID = bv.businessID
AND bc.userId = bv.userId
AND bc.createdAt < bv.createdAt
ORDER BY bc.id DESC
LIMIT 1
) bcs ON true
WHERE bv.businessId = 1;
I have included the CTEs to save others the effort, if they fancy trying this.
If i understand correctly :
SELECT
Count(case when bc.id is null end) as client
, count(case when bc.id is not null end) as non-client
FROM BusinessViews bv
Left join BusinessClients bc
On bv.businessid = bc.businessid
WHERE bv.businessId = 1
GROUP BY bv.businessId
I have a table called statuses shown below. Every time a user logs in a row is added. A status is added. I need to write a query that gives me all IDs one time that have never been 1, 6 or 8.
id
status
1
1
1
6
1
8
1
1
2
1
2
6
2
8
2
0
3
0
3
0
3
0
3
0
I wrote a query:
SELECT DISTINCT(id) FROM statuses WHERE status NOT IN (1, 6, 8)
Unfortunately this gives me ID 2 and 3, but I don't want ID 2 to be selected because they have statuses 1, 6, and 8.
Thanks for your help!
You can group by id and set the condition in the HAVING clause:
SELECT id
FROM statuses
GROUP BY id
HAVING SUM(status IN (1, 6, 8)) = 0
Or:
SELECT DISTINCT id
FROM statuses
WHERE id NOT IN (SELECT id FROM statuses WHERE status IN (1, 6, 8))
See the demo.
I have the following problem at work. I have a large table with different columns and few 100 000s of rows. I'll only post the ones im interested in.
Assume the following data set
Device ID, Feature Id, Feature Status
1, 1, 0
1, 2, 0
1, 3, 1
1, 4, 1
1, 5, 1
2, 1, 1
2, 2, 0
2, 3, 0
2, 4, 1
2, 5, 0
3, 1, 1
3, 2, 1
3, 3, 1
3, 4, 1
3, 5, 1
4, 1, 0
4, 2, 0
4, 3, 1
4, 4, 0
4, 5, 0
I need to select rows with Feature Status = 1 but only the first 2 from each Device Id.
The results of the query should be:
1,3,1
1,4,1
2,1,1
2,4,1
3,1,1
3,2,1
4,3,1
I tried something like this:
SELECT brdsurfid,featureidx,FeatStatus FROM Features F1 WHERE FeatStatus = 1 AND
(SELECT COUNT(*) FROM Features F2
WHERE F2.FeatureIdx <= F1.FeatureIdx AND F2.FeatStatus = 1) < 2
ORDER BY BrdSurfId,FeatureIdx;
which I found in another response but it didnt quite work.
I know I need to use a mix of LIMIT or COunt(*) and some nested selects but I can't figure it out. Thanks
This probably not a very efficient way to do this, but I don't think there is a better solution for sqlite (that involves a single query):
SELECT *
FROM t t0
WHERE FeatureStatus AND
(SELECT count(*)
FROM t t1
WHERE t0.DeviceID=t1.DeviceID
AND FeatureStatus
AND t1.FeatureId<t0.FeatureId
)<2;
I assume that the table is called t. The idea is to find all features where the status is 1 and then for each feature to count the previous features with that status for the same product. If that count is more than 2, then reject the row.
Not sure if this will work with sqlite but for what its worth...
;with result as
(
SELECT
brdsurfid,
featureidx,
FeatStatus ,
ROW_NUMBER() OVER(PARTITION BY brdsurfid ORDER BY fieldWhatever) AS 'someName1',
ROW_NUMBER() OVER(PARTITION BY featureidx ORDER BY fieldWhatever) AS 'someName2',
ROW_NUMBER() OVER(PARTITION BY FeatStatus ORDER BY fieldWhatever) AS 'someName3'
FROM
Features
)
SELECT *
FROM
result
WHERE
FeatStatus = 1 AND
someName1 <= 2 AND
someName2 <= 2 AND
someName3 <= 2
I'm sure this is possible I don't know where to start.
I have a table with 2000 values they are on the range from 0 to 100.
I want to query the table to get the different groups of values.
i.e. I have those values 5, 10 , 5 , 2 , 2, 0, 1, 1, 1, 1, 1, 10, 2
I want an output like this:
Value - Number_of_times
0 1
1 5
2 3
5 2
10 2
You need to group your results by your field, and take the COUNT() of each group:
SELECT myfield, COUNT(*) as number_of_times
FROM mytable
GROUP BY myfield
given a users qualification id's how would you find the jobs they can do using SQL?
1) for example a user with only qualification 1 could only do job3
and not 1 and 4 because you need more than one qualification.
2) a user with qualifications 1 and 2 could do jobs 1 and 3 but not 4
JOBDETAILS TABLE
JobID ,QualificationID
1, 1
1, 2
3, 1
4, 1
4, 2
4, 3
thanks for any help
TJ
SELECT DISTINCT JobID
FROM JobDetails
WHERE QualificationID IN (#Quals)
AND JobID NOT IN
(
SELECT DISTINCT JobID
FROM JobDetails
WHERE QualificationID NOT IN (#Quals)
)
(Apologies for syntax issues; I work with SQL Server, not MySQL)