I am creating a jsp page where a single news item is shown, just like the single question on this StackOverflow page. I need to store the view count in a database.
I can simply increment the view count in the database this way:
`UPDATE table SET views=views+1 WHERE newsId=4458;`
But what if a single user hits that page again and again and again, say 50 times... In this case, my view count will not represent unique visitors to the site. How can I avoid this?
I want something like StackOverflow's view count system.
well one solution could be you make a new table (lets say its called views) with the following columns 'viewid' 'newsid' 'ipaddress' (obviously newsid is the foreign key)
every time someone visits ur website u check if his ip is already in that table for that news item.
Select count(*) AS count FROM views WHERE newsid=1234 AND ipaddress=123.456.125
if count equals 0 you insert like this
INSERT INTO views('newsid', 'ipaddress') VALUES(1234, 123.146.125)
Now when you want to fetch the viewcount:
Select count(*) AS count FROM views WHERE newsid=1234
you can enhance this by adding another column called 'count' and 'lastviewed' (type datetime) to the table views.
Lets say you allow every ip to be counted another time if the day doesnt match.
This way you will get a pretty accurate viewcount :)
to fetch the new viewcount you can simply use SUM
Select SUM(count) AS count WHERE newsid=1234
Good luck :)
You may want to reference spencer7593's answer here, where he basically suggests having both (1) a view count column, for quickly generating your webpages and (2) a separate views table, which records the user id and timestamp pertaining to each view, for the sake of analytics.
I would suggest that this views table could also be used to query if a viewing has occurred for a particular user with a particular piece of content in the last day (or week) when determining if the view count column should be incremented. By checking if a view of a certain item has occurred only in the last day (or week), the DB queries should be substantially less expensive while still protecting the integrity of your view count.
i say use a counter in Javscript . Increment the variable on body onclick. eg:
<script language=”javascript”>
function pageCounter()
{
var counter = 0;
counter = counter++;
}
</script>
<body onclick = “pageCounter()”>
and you can update the value with onclose ..
Related
I am working on a mock airline ticket reservation app using javascript and a postgres database.
--EDITED--
I need to create a function/trigger that will only allow me to insert a new row in my TICKET if the number of tickets for a flight does not exceed the max number of seats for the aircraft.
How do you write a function isolates single values from queries:
1)SELECT count(*) FROM ticket WHERE flight_id = x
2)SELECT maxSeats FROM airplane where aircraft_code = (code for for airplane the correlates with flight).
How do I get single values from these two queries to check (number of seats <= max_seats).
Thanks.
I need to do a transaction that does the following: -INSERT new row in TICKET table that includes a foreign key(flight_id) that references the FLIGHT table. -UPDATE the number of seats(increment by one) in the FLIGHT table for the flight(flight_id) that the ticket was just inserted.
You can derive the "number of seats" by SELECT COUNT(*) FROM TICKET WHERE flight_id = {flight_id}. Adding a number of seats attribute in FLIGHT would be a normalisation error and force you to keep it in sync with the TICKETs for the FLIGHT.
Do I need to use a trigger or function for this that will simply throw an error when I try to commit? or is there a way to set up a special kind of constraint for a column that references the value in another table(ie. FLIGHT.num_seats_booked < AIRPLANE.max_num_seats.)
In a platform that supports it, you could add a CHECK constraint that calls a function to do the necessary checks by querying other tables. As far as I know, while you can do this in Postgres, there are problems re concurrent updates and it is recommended using triggers.
I need to only commit the above transaction if their are still seats available for the flight.
Or should I be using an IF/ELSE query inside of my transaction?
Just looking to get pointed in the general right direction on how to approach this kind of problem
Not relevant with Postgres, but check this thread if you are interested
How do i go about writing a function that compares number of tickets for a flight and max_seats for an airplane? I'm not sure how to grab a single value from two queries to compare them and return true or false in a function.
Something like this would work:
SELECT COUNT(*) < (
SELECT MaxSeats
FROM Flight
INNER JOIN Aircraft
ON Aircraft.AircraftCode = Flight.AircraftCode
WHERE FlightId = {flightId})
FROM Ticket
WHERE FlightId = {flightId}
I have:
a table with user names
a table indicating actions with columns for user name, action time, action name. Named events unique_events
I started collecting data on January. I want to have a column in my table of user names which indicates how long it has been since a user first used my application and the first of January.
So if a user first logged in in January, the value of the row with that user's name will be 0. If one logged in on March it will be 2.
I tried:
Column = DATEDIFF(01-01-2016, MIN(SELECTCOLUMNS(FILTER('events unique_events','events unique_events'[User Name] = Users[User Name]),"DatedTime", [DatedTime])),MONTH)
which returns an error saying the Min function needs a column reference.
I also tried the same with FirstDate instead of MIN which returned an error saying FirstDate can't be used with summarize functions.
Any other ideas on how to achieve this, or fix what I tried?
(for simplicity, I will call your table 'Events', and user login dates field 'User_Login_Date').
First, define your app start date as a measure:
App_Start_Date:= DATE(2016, 1, 1)
Then, define measure that finds min differences between Application Start Date and User Login dates:
User_Start_Diff=: MINX(Events, DATEDIFF([App_Start_Date], Events[User_Login_Date], Month))
Drop this measure into a pivot table against user names, and you should have your desired result.
How it works:
1) MINX goes record by record and calculates date differences for each customer login. It then finds minimum in the results;
2) When you drop the measure into a pivot table, it splits MINX results by customer, and recalculates min for each of them separately. You don't need to do the grouping.
Creation of [Start_Date] measure is not technically necessary but a matter of good style - don't hardcode values in your formulas, always create measures. You will thank yourself later when you need to make a change.
I am trying to loop through Column Values inside my Table.
I have a register form, which provides the user with UNIQUE ID, based uppon his information.
For example:
Country = Austria
Each user that selects country Austria will get some sort of Unique Value for that match (lets say 00).
Account ID look like this:
XXXX00UNIQUECODE
Each country has it´s own unique value: (AT = 00, DE = 01, etc)
Now, I want to generate a UNIQUE CODE for each user, that will be just an increment (+1) value of the previous UC value stored in the table, for the same country!
In order to do that, I need to somehow loop through the Column, where the Account IDs are stored and search for the match.
The thing is, when a user tries to generate the UNIQUE CODE, he does not have it yet, so he has only:
XXXX00
Now I need to find all the XXXX00 strings in my AccountID Column, and store them in an Array - then find the Max Value of those and increment it.
BUT I dont know how to search for a part of the string inside a Column of the Table ?
Just the XXXX00 part, not the entire Account ID XXXX00UNIQUECODE.
Agh, I hope you can understand me. It´s quite complicated I know, but I´m really stuck here. Hopefully, someone will know what I mean and maybe even find a smoother solutions for this.
Thanks in advance!
You're pounding a square peg into a round hole. Why not just create a new column called UserID and then you can do:
SELECT Max(UserID) FROM MyTable WHERE Mid(AccountID, 5, 2) = "00"
and increment it by 1.
Better yet, store CountryCode, UserID and the XXXX part in separate fields, and index them. It'll save time when you search or filter, which I'm assume you're going to be doing.
I have a view setup with a map reduce. Right now this code works great:
function(doc) {
if (doc.type == 'test'){
if(doc.trash != 1){
for (var id in doc.items) {
emit([id,doc.items[id].name], 1);
}
}
}
}
function(keys,prices){
return (keys, sum(prices));
}
I get a return and when using the group parameter, it condenses everything just fine.
My issue/question, I want to add a third key.... DATE, so I may only reduce records from certain dates. So for example:
function(doc) {
if (doc.type == 'test'){
if(doc.trash != 1){
for (var id in doc.items) {
emit([date,id,doc.items[id].name], 1);
}
}
}
}
My issue is that since date is at the beginning of the array, the reduce groups by date, id etc. I know I use group_level and say just take the first key from the array or the first 2 keys, but that doesn't help either because afaik, group_level goes from left to right in the array. I could put the date on the end of the emit array, but that doesn't help either because I need to have values at the beginning of my startkey and endkey to search on.
Here is an example of the output of data:
{"key":["2012-03-13","356752b8a5f6871f3","Apple"],"value":1},
{"key":["2012-03-20","123752b8a76986857","Pear"],"value":1},
{"key":["2012-04-12","3013531de05871194","Grapefruit"],"value":1},
{"key":["2012-04-12","356752b8a5f6871f3","Apple"],"value":1},
I want APPLE to be added up in one row, here it's adding up apples by date first. I was able to successfully just add up all the apples if I remove DATE as the first key in the array, but then I can't search by date range.
Any ideas on how to accomplish this?
If I correctly understand what you want to do, then you'd want to put the date as the first element of your array, and use group_level as well as start_key and end_key.
Eg. startkey=[1, "someid"] endkey=[1,"someid",{}] group_level=2
Will get you all items from date 1 (obviously choose your own format here), with id "someid" and any name. It seems funny that you emit id's before names, and without having more information about what you're actually trying to accomplish, it's hard to advise your general data model. If ID is a "type" id meaning that many items share the same ID then this makes sense. If ID is a unique per item ID, then it does not. In that case, you'd want to emit "name" before ID...
Edit 1
As per your comment, to do a range of dates you do this:
startkey=[1] endkey=[5,{}] group_level=2
You will get everything from date 1 to date 5 grouped by id ie. apples, oranges etc. I use this exact technique in a very large scale production application. I actually formatted the dates as an easily human readable integers of the format yyyymmdd, so 20140624 would sort to the top. If I want everything from the start of the month till now grouped by my group ids, I call
startkey=[20140601] endkey=[20140624,{}] group_level=2
It works perfectly and as far as I can tell that's what you're looking to do. I also have a third key layer "detail" which allows me to provide a deeper level of grouping for items that need it. I can then call
startkey=[20140601, "someid"] endkey=[20140624, "someid",{}] group_level=3
To drill to the detail level for a particular id, or just use the previous query with group_level=3 if I want the details for every id. I'm certain you can make this work - I've solved this exact problem in a production application using the techniques described.
Edit 2
If you want to group all apples regardless of date, then you'll need to let apples be the first element in the key. You can then get all apples over all time as a single row in the view result using group_level=1, and Apples over a date range using group_level=2. The difference here is that you'll only be able to do the group_level=2 query on a single item type at a time. If you want the best of both worlds, you unfortunately just need to make 2 views. That's just how key ordering works... If you need fast response times for both types of queries, all item types over a date range, and all of a particular item not grouped by date, I believe 2 views is the only way to achieve that.
Note
Another thing to note is about your reduce function. Wherever possible it is highly recommended that you use the built in reduce functions. They're implemented in erlang and are highly optimized compared to custom javascript reduce functions.
In your case, just replace your reduce function with this
_sum
Easy hey?
If you post more info about your application, data model etc. then I'd be happy to help out more with your database design.
I have a MVC application in which I need to display the data from 3 tables. I am using entity model for it. Out of these, in 2 I have made the association:users and payment table.
And 3rd table month_<monthid> is created every month to store the users to whom the magazine is sent. The table name month_<monthid> is generated dynamically by selecting the month so in order to fetch the data I have used ExeuteStoreQuery. For small amount of data the listing is fast but for large amount it is very slow.
Now I have created a class to bind to grid which will include all the fields from the 3 tables to display.
But here when I am getting the large volume of data about 12000 then it is taking about 30 min to go through the loop and assigning the data to the class object and then adding to the list of the result which is finally binded to telerik grid.
I am hereby attaching the sample code using a link. Is there any direct way to bind the query result of joined tables to grid instead of going through the loop and preparing the list for the model class I think that will save time.
The code block of preparing the list using the Executestorequery is under the function GetuserList().
foreach (var r in result)
{
Result objresult = new Result();
var paymentresult = from sub in dtpayment.AsEnumerable() where sub.Field<int>("user_id") == r.user_id select sub;
if (paymentresult.Count() > 0)
{
objresult.amount_paid = paymentresult.FirstOrDefault().Field<decimal>("amount_paid");
objresult.magzine_id = paymentresult.FirstOrDefault().Field<int>("magzine_id");
}
objresult.address=r.address;
objresult.email=r.email;
objresult.name=r.name;
objresult.user_id=r.user_id;
objresult.month= smonth;
lstresult.Add(objresult);
}
This code block of for loop is taking very time where I am using ExceuteStoreQuery.
But I have observed that simply by joining the users and payment table using LINQ query to get all the 12000 records i.e no involvement of month table the result is appearing faster.
So,can you suggest any way to improve the performance of my application?
Also include the database structure with the sample code.
Below is the link to sample
http://sampletestone.s3.amazonaws.com/magzine.7z?AWSAccessKeyId=AKIAINHDRCMKC5GUSNFA&Expires=1303583399&Signature=8o8Wn6UNjbEl3dIyipAX9xH29Hg%3D
supriya
Nobody in the world wants to see 12,000 records. You should look at implementing paging & searching functionality.